Skip to content

Commit

Permalink
feat(workflows): sensor and trigger to sync keystone to nautobot
Browse files Browse the repository at this point in the history
Added an EventSource listener for keystone notifications. Added a Sensor
to trigger a workflow to be run when projects are created, updated or
deleted in keystone. Added a workflow to execute the keystone sync
script on each of those triggers.
  • Loading branch information
cardoe committed Sep 9, 2024
1 parent 713e46d commit 431e8b6
Show file tree
Hide file tree
Showing 11 changed files with 252 additions and 1 deletion.
1 change: 1 addition & 0 deletions .github/workflows/yamllint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ jobs:
argo-workflows/**/workflowtemplates/*.y*ml
argo-workflows/**/sensors/*.y*ml
argo-workflows/**/workflows/*.y*ml
apps/understack-workflows/workflows/workflowtemplates/*.y*ml
shellcheck:
runs-on: ubuntu-latest
Expand Down
16 changes: 16 additions & 0 deletions apps/understack-workflows/eventsource-openstack/argo-rabbitmq.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,19 @@ spec:
rabbitmqClusterReference:
name: rabbitmq # rabbitmqCluster must exist in the same namespace as this resource
namespace: openstack
---
apiVersion: rabbitmq.com/v1beta1
kind: Permission
metadata:
name: argo-to-keystone-permission
spec:
vhost: "keystone"
userReference:
name: "argo" # name of a user.rabbitmq.com in the same namespace; must specify either spec.userReference or spec.user
permissions:
write: ".*"
configure: ".*"
read: ".*"
rabbitmqClusterReference:
name: rabbitmq # rabbitmqCluster must exist in the same namespace as this resource
namespace: openstack
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ resources:
- argo-rabbitmq.yaml
- eventbus-default.yaml
- openstack-event-source.yaml
- sensor-keystone-event-project.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ spec:
openstack:
# amqp server url
url: amqp://rabbitmq-server-0.rabbitmq-nodes.openstack.svc.cluster.local:5672/ironic
routingKey: 'ironic_versioned_notifications.info'
# jsonBody specifies that all event body payload coming from this
# source will be JSON
jsonBody: true
Expand All @@ -16,6 +15,44 @@ spec:
exchangeType: topic
exchangeDeclare:
durable: false
# routing key for messages within the exchange
routingKey: 'ironic_versioned_notifications.info'
# optional consume settings
# if not provided, default values will be used
consume:
consumerTag: "argo-events"
autoAck: true
exclusive: false
noLocal: false
# username and password for authentication
# use secret selectors
auth:
username:
name: argo-user-credentials
key: username
password:
name: argo-user-credentials
key: password
---
apiVersion: argoproj.io/v1alpha1
kind: EventSource
metadata:
name: openstack-keystone
spec:
amqp:
notifications:
# amqp server url
url: amqp://rabbitmq-server-0.rabbitmq-nodes.openstack.svc.cluster.local:5672/keystone
# jsonBody specifies that all event body payload coming from this
# source will be JSON
jsonBody: true
# name of the exchange.
exchangeName: keystone
exchangeType: topic
exchangeDeclare:
durable: false
# routing key for messages within the exchange
routingKey: 'notifications.info'
# optional consume settings
# if not provided, default values will be used
consume:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: sensor-submit-workflow
---
apiVersion: argoproj.io/v1alpha1
kind: Sensor
metadata:
finalizers:
- sensor-controller
labels:
argocd.argoproj.io/instance: argo-events
name: keystone-event-project
namespace: argo-events
annotations:
workflows.argoproj.io/description: |
Defined in `apps/understack-workflows/sensors/sensor-keystone-event-project.yaml`
spec:
dependencies:
- eventName: notifications
eventSourceName: openstack-keystone
name: keystone-msg
transform:
jq: ".body[\"oslo.message\"] | fromjson"
filters:
dataLogicalOperator: "and"
data:
- path: "event_type"
type: "string"
value:
- "identity.project.created"
- "identity.project.updated"
- "identity.project.deleted"
template:
serviceAccountName: sensor-submit-workflow
triggers:
- template:
name: keystone-event-project
argoWorkflow:
operation: submit
parameters:
- dest: spec.arguments.parameters.0.value
src:
dataKey: event_type
dependencyName: keystone-msg
- dest: spec.arguments.parameters.1.value
src:
dataKey: payload.target.id
dependencyName: keystone-msg
source:
resource:
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: keystone-event-project-
namespace: argo-events
spec:
arguments:
parameters:
- name: event_type
value: "replaced by parameters section"
- name: project_uuid
value: "replaced by parameters section"
serviceAccountName: workflow
workflowTemplateRef:
name: keystone-event-project
1 change: 1 addition & 0 deletions apps/understack-workflows/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ kind: Kustomization

resources:
- eventsource-openstack
- workflowtemplates
10 changes: 10 additions & 0 deletions apps/understack-workflows/workflows/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

# this is where our workflows currently run
namespace: argo-events

resources:
- openstack-svc-acct.yaml
- sensor-submit-rbac.yaml
- workflowtemplates/keystone-event-project.yaml
28 changes: 28 additions & 0 deletions apps/understack-workflows/workflows/openstack-svc-acct.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: openstack-svc-acct
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: openstack
target:
name: openstack-svc-acct
template:
engineVersion: v2
data:
clouds.yaml: |
clouds:
understack:
auth_url: http://keystone-api.openstack.svc.cluster.local:5000/v3
user_domain_name: {{ .user_domain }}
username: {{ .username }}
password: {{ .password }}
# this should switch to where we will be creating the ironic nodes
# in the future
project_domain_name: default
project_name: undercloud
dataFrom:
- extract:
key: svc-acct-argoworkflow
40 changes: 40 additions & 0 deletions apps/understack-workflows/workflows/sensor-submit-rbac.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
# Similarly you can use a ClusterRole and ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: sensor-submit-workflow-role
rules:
- apiGroups:
- argoproj.io
verbs:
- get
- watch
- list
resources:
- workflowtemplates
- clusterworkflowtemplates
- apiGroups:
- argoproj.io
verbs:
- create
- get
- list
- watch
- update
- patch
resources:
- workflows
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: openstack-sensor-submit-workflow
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: sensor-submit-workflow-role
subjects:
- kind: ServiceAccount
name: sensor-submit-workflow
namespace: openstack
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
apiVersion: argoproj.io/v1alpha1
metadata:
name: keystone-event-project
annotations:
workflows.argoproj.io/description: |
Defined in `apps/understack-workflows/workflowtemplates/wf-keystone-event-project.yaml`
kind: WorkflowTemplate
spec:
entrypoint: sync-keystone
templates:
- name: sync-keystone
container:
image: ghcr.io/rackerlabs/understack/ironic-nautobot-client:latest
command:
- sync-keystone
args:
- "--only-domain"
- "default"
- "{{workflow.parameters.event_type}}"
- "{{workflow.parameters.project_uuid}}"
volumeMounts:
- mountPath: /etc/nb-token/
name: nb-token
readOnly: true
- mountPath: /etc/openstack
name: openstack-svc-acct
readOnly: true
inputs:
parameters:
- name: project_uuid
volumes:
- name: nb-token
secret:
secretName: nautobot-token
- name: openstack-svc-acct
secret:
secretName: openstack-svc-acct
13 changes: 13 additions & 0 deletions docs/component-understack-workflows.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ time it is listening to keystone and ironic only.

1. An [Argo Events][argo-events] Event Bus
to push the received notifications into.
1. A Kubernetes Service account `sensor-submit-workflow` which
allows an Argo Events Trigger from a Sensor to read look up
[Argo Workflows][argo-wf] Workflow Templates and use them to
execute a Workflow.
1. An [Argo Events][argo-events] Sensors and Triggers that
execute workflows.

## workflowtemplates

1. A Kubernetes Role Binding allowing the `sensor-submit-workflow`
the access it needs to run Workflows.
1. A number of Workflow Templates.

[argo-events]: <https://argoproj.github.io/argo-events/>
[argo-wf]: <https://argo-workflows.readthedocs.io/en/latest/>
[eso]: <https://external-secrets.io>

0 comments on commit 431e8b6

Please sign in to comment.