Skip to content

Latest commit

 

History

History
157 lines (122 loc) · 5.57 KB

File metadata and controls

157 lines (122 loc) · 5.57 KB

Cert Manager Notifications

The example demonstrates how Notifications Engine can be used to implement notifications for Cert-Manager Certificate CRD.

Controller

The machinery required for controller implementation is provided by pkg/controller and pkg/api packages.

  • The first step is to write the boilerplate code required to get Kubernetes REST config so we can talk to API server.

  • Next create ConfigMap and Secret informers and use it to initialize api.Factory:

informersFactory := informers.NewSharedInformerFactoryWithOptions(
	kubernetes.NewForConfigOrDie(restConfig),
	time.Minute,
	informers.WithNamespace(namespace))
secrets := informersFactory.Core().V1().Secrets().Informer()
configMaps := informersFactory.Core().V1().ConfigMaps().Informer()
notificationsFactory := api.NewFactory(api.Settings{
	ConfigMapName: "cert-manager-notifications-cm",
	SecretName:    "cert-manager-notifications-secret",
	InitGetVars: func(cfg *api.Config, configMap *v1.ConfigMap, secret *v1.Secret) (api.GetVars, error) {
		return func(obj map[string]interface{}, dest services.Destination) map[string]interface{} {
			return map[string]interface{}{"cert": obj}
		}, nil
	},
}, namespace, secrets, configMaps)
  • Next step is to create the NotificationController:
certClient := dynamic.NewForConfigOrDie(restConfig).Resource(schema.GroupVersionResource{
	Group: "cert-manager.io", Version: "v1", Resource: "certificates",
})
certsInformer := cache.NewSharedIndexInformer(&cache.ListWatch{
	ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
		return certClient.List(context.Background(), options)
	},
	WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
		return certClient.Watch(context.Background(), metav1.ListOptions{})
	},
}, &unstructured.Unstructured{}, time.Minute, cache.Indexers{})
ctrl := controller.NewController(certClient, certsInformer, notificationsFactory)
  • Finally "start" informers and run the controller:
go informersFactory.Start(context.Background().Done())
go certsInformer.Run(context.Background().Done())
if !cache.WaitForCacheSync(context.Background().Done(), secrets.HasSynced, configMaps.HasSynced, certsInformer.HasSynced) {
	log.Fatalf("Failed to synchronize informers")
}
ctrl.Run(10, context.Background().Done())

Done! Your controller is ready. The full code listing is available in controller/main.go. You can clone this repository and use go run examples/certmanager/controller/main.go to start it.

Configuration

The next step is to create a trigger, notification template, and configure integration with the notification service. The example below demonstrates on-cert-ready trigger which sends a notification using cert-ready template when the Certificate is ready:

apiVersion: v1
kind: ConfigMap
metadata:
  name: cert-manager-notifications-cm
data:
  trigger.on-cert-ready: |
    - when: any(cert.status.conditions, {.reason == 'Ready' && .status == 'True'})
      send: [cert-ready]

  template.cert-ready: |
    message: |
      Certificate {{.cert.metadata.name}} is ready!

  service.slack: |
    token: $slack-token

Apply the sample configuration using the following command:

kubectl apply -f ./examples/certmanager/config.yaml

The example configures integration with Slack. Following the steps described in slack to get the Slack token and create cert-manager-notification-secret Secret using the following command:

kubectl create secret generic cert-manager-notification-secret --from-literal slack-token=<SLACK-TOKEN>

Finally annotate the certificate to subscribe to the on-cert-ready trigger and get the notification:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  annotations:
    notifications.argoproj.io/subscribe.on-cert-ready.slack: <CHANNEL>

Debugging Tools

The CRD specific triggers and templates create true value for end-users. However, it might be challenging for the CRD controller administrator to create more of them. The simplify administrators life the Notification Engine includes pkg/cmd package that provides debugging CLI tool implementation. CLI tool provides commands to run triggers/templates configured in the live Kubernetes cluster or in the local YAML file. Use the following snippet to create CLI for Cert Manager configuration debugging:

func main() {
	command := cmd.NewToolsCommand("cli", "cli", schema.GroupVersionResource{
		Group: "cert-manager.io", Version: "v1", Resource: "certificates",
	}, api.Settings{
		ConfigMapName: "cert-manager-notifications-cm",
		SecretName:    "cert-manager-notifications-secret",
		InitGetVars: func(cfg *api.Config, configMap *v1.ConfigMap, secret *v1.Secret) (api.GetVars, error) {
			return func(obj map[string]interface{}, dest services.Destination) map[string]interface{} {
				return map[string]interface{}{"cert": obj}
			}, nil
		},
	})

	if err := command.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

The full source code is available in cli/main.go. Use the following command:

  • to list avilable templates:
go run examples/certmanager/cli/main.go template get --config-map ./examples/certmanager/config.yaml --secret :empty
  • to "run" on-cert-ready trigger:
go run examples/certmanager/cli/main.go trigger run on-cert-ready <MY-CERT> --config-map ./examples/certmanager/config.yaml --secret :empty
  • to see what else is available:
go run examples/certmanager/cli/main.go --help