Skip to content

Commit 0d65023

Browse files
committed
Add example operation function
Signed-off-by: Nic Cope <[email protected]>
1 parent 66830b6 commit 0d65023

File tree

8 files changed

+104
-0
lines changed

8 files changed

+104
-0
lines changed
File renamed without changes.

example/operation/functions.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
apiVersion: pkg.crossplane.io/v1beta1
3+
kind: Function
4+
metadata:
5+
name: function-python
6+
annotations:
7+
# This tells crossplane beta render to connect to the function locally.
8+
render.crossplane.io/runtime: Development
9+
spec:
10+
# This is ignored when using the Development runtime.
11+
package: function-python

example/operation/ingress.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
apiVersion: networking.k8s.io/v1
2+
kind: Ingress
3+
metadata:
4+
name: example-ingress
5+
namespace: default
6+
spec:
7+
rules:
8+
- host: google.com
9+
http:
10+
paths:
11+
- path: /
12+
pathType: Prefix
13+
backend:
14+
service:
15+
name: example-service
16+
port:
17+
number: 80

example/operation/operation.yaml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
apiVersion: ops.crossplane.io/v1alpha1
2+
kind: Operation
3+
metadata:
4+
name: check-cert-expiry
5+
spec:
6+
mode: Pipeline
7+
pipeline:
8+
- step: check-certificate
9+
functionRef:
10+
name: function-python
11+
requirements:
12+
requiredResources:
13+
- requirementName: ingress
14+
apiVersion: networking.k8s.io/v1
15+
kind: Ingress
16+
name: example-ingress
17+
namespace: default
18+
input:
19+
apiVersion: python.fn.crossplane.io/v1beta1
20+
kind: Script
21+
script: |
22+
import ssl
23+
import socket
24+
from datetime import datetime
25+
26+
def operate(req, rsp):
27+
# Get the Ingress resource
28+
ingress = req.required_resources["ingress"].resource
29+
30+
# Extract hostname from Ingress rules
31+
hostname = ingress["spec"]["rules"][0]["host"]
32+
port = 443
33+
34+
# Get SSL certificate info
35+
context = ssl.create_default_context()
36+
with socket.create_connection((hostname, port)) as sock:
37+
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
38+
cert = ssock.getpeercert()
39+
40+
# Parse expiration date
41+
expiry_date = datetime.strptime(cert['notAfter'], '%b %d %H:%M:%S %Y %Z')
42+
days_until_expiry = (expiry_date - datetime.now()).days
43+
44+
# Annotate the Ingress with certificate expiry info
45+
rsp.desired.resources["ingress"].resource.update({
46+
"apiVersion": "networking.k8s.io/v1",
47+
"kind": "Ingress",
48+
"metadata": {
49+
"name": ingress["metadata"]["name"],
50+
"namespace": ingress["metadata"]["namespace"],
51+
"annotations": {
52+
"cert-monitor.crossplane.io/expires": cert['notAfter'],
53+
"cert-monitor.crossplane.io/days-until-expiry": str(days_until_expiry),
54+
"cert-monitor.crossplane.io/status": "warning" if days_until_expiry < 30 else "ok"
55+
}
56+
}
57+
})
58+
59+
# Return results in operation output for monitoring
60+
rsp.output.update({
61+
"hostname": hostname,
62+
"certificateExpires": cert['notAfter'],
63+
"daysUntilExpiry": days_until_expiry,
64+
"status": "warning" if days_until_expiry < 30 else "ok"
65+
})

example/operation/rbac.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
apiVersion: rbac.authorization.k8s.io/v1
2+
kind: ClusterRole
3+
metadata:
4+
name: operation-ingress-access
5+
labels:
6+
rbac.crossplane.io/aggregate-to-crossplane: "true"
7+
rules:
8+
# Allow Operations to read and update Ingress resources
9+
- apiGroups: ["networking.k8s.io"]
10+
resources: ["ingresses"]
11+
verbs: ["get", "list", "patch", "update"]

0 commit comments

Comments
 (0)