-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
281 additions
and
0 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
Empty file.
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,44 @@ | ||
import argparse | ||
import logging | ||
import os | ||
import sys | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def setup_logger(name): | ||
logger = logging.getLogger(name) | ||
handler = logging.StreamHandler() | ||
formatter = logging.Formatter( | ||
"%(asctime)s - %(name)s - %(levelname)s - %(message)s" | ||
) | ||
handler.setFormatter(formatter) | ||
logger.addHandler(handler) | ||
logger.setLevel(logging.DEBUG) | ||
return logger | ||
|
||
|
||
def arg_parser(name): | ||
parser = argparse.ArgumentParser( | ||
prog=os.path.basename(name), description="Ironic to Nautobot provisioning state sync" | ||
) | ||
parser.add_argument("--device_uuid", required=True, | ||
help="Nautobot device UUID") | ||
parser.add_argument("--provisioning-state", required=True) | ||
parser.add_argument("--nautobot_url", required=False) | ||
parser.add_argument("--nautobot_token", required=False) | ||
|
||
return parser | ||
|
||
|
||
def exit_with_error(error): | ||
logger.error(error) | ||
sys.exit(1) | ||
|
||
|
||
def credential(subpath, item): | ||
try: | ||
return open(f"/etc/{subpath}/{item}", "r").read().strip() | ||
except FileNotFoundError: | ||
exit_with_error(f"{subpath} {item} not found in mounted files") | ||
|
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,24 @@ | ||
from nautobot import Nautobot | ||
from helpers import arg_parser | ||
from helpers import credential | ||
from helpers import setup_logger | ||
|
||
logger = setup_logger(__name__) | ||
|
||
|
||
def main(): | ||
parser = arg_parser(__file__) | ||
args = parser.parse_args() | ||
|
||
default_nb_url = "http://nautobot-default.nautobot.svc.cluster.local" | ||
device_uuid = args.device_uuid | ||
provision_state = args.provisioning_state | ||
nb_url = args.nautobot_url or default_nb_url | ||
nb_token = args.nautobot_token or credential("nb-token", "token") | ||
|
||
nautobot = Nautobot(nb_url, nb_token, logger=logger) | ||
nautobot.update_status(device_uuid, provision_state) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
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,67 @@ | ||
import logging | ||
import pynautobot | ||
import requests | ||
import sys | ||
from typing import Protocol | ||
from pynautobot.core.api import Api as NautobotApi | ||
from pynautobot.models.dcim import Devices as NautobotDevice | ||
|
||
class Nautobot: | ||
ALLOWED_STATUSES = [ | ||
'enroll', | ||
'verifying', | ||
'manageable', | ||
'inspecting', | ||
'inspect wait', | ||
'inspect failed', | ||
'cleaning', | ||
'clean wait', | ||
'available', | ||
'deploying', | ||
'wait call-back' | ||
'deploy failed', | ||
'active', | ||
'deleting', | ||
'error', | ||
'adopting', | ||
'rescuing' | ||
'rescue wait', | ||
'rescue failed', | ||
'rescue', | ||
'unrescuing', | ||
'unrescue failed', | ||
'servicing', | ||
'service wait', | ||
'service failed' | ||
] | ||
def __init__(self, url, token, logger=None, session=None): | ||
self.url = url | ||
self.token = token | ||
self.logger = logger or logging.getLogger(__name__) | ||
self.session = session or self.api_session(self.url, self.token) | ||
|
||
def exit_with_error(self, error): | ||
self.logger.error(error) | ||
sys.exit(1) | ||
|
||
def api_session(self, url: str, token: str) -> NautobotApi: | ||
try: | ||
return pynautobot.api(url, token=token) | ||
except requests.exceptions.ConnectionError as e: | ||
self.exit_with_error(e) | ||
except pynautobot.core.query.RequestError as e: | ||
self.exit_with_error(e) | ||
|
||
def device_by_id(self, device_id: str) -> NautobotDevice: | ||
device = self.session.dcim.devices.get(device_id) | ||
if not device: | ||
self.exit_with_error(f"Device {device_id} not found in Nautobot") | ||
return device | ||
|
||
def update_status(self, device_id, new_status: str): | ||
device = self.device_by_id(device_id) | ||
|
||
if new_status not in self.ALLOWED_STATUSES: | ||
raise Exception(f"Status {new_status} for device {device_id} is not in ALLOWED_STATUSES.") | ||
|
||
return device.update({"status": new_status}) |
30 changes: 30 additions & 0 deletions
30
argo-workflows/ironic-to-nautobot-sync/containers/Dockerfile
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,30 @@ | ||
ARG BASE=ghcr.io/rackerlabs/understack/argo-python3.11.8-alpine3.19:latest | ||
|
||
FROM ${BASE} as builder | ||
|
||
ARG APP_PATH=/app | ||
ARG APP_USER=appuser | ||
ARG APP_GROUP=appgroup | ||
ARG APP_USER_UID=1000 | ||
ARG APP_GROUP_GID=1000 | ||
|
||
COPY --chown=${APP_USER}:${APP_GROUP} containers/requirements.txt /app | ||
RUN --mount=type=cache,target=/var/cache/apk apk add --virtual build-deps gcc python3-dev musl-dev linux-headers | ||
RUN --mount=type=cache,target=/root/.cache/.pip pip install --no-cache-dir -r /app/requirements.txt | ||
|
||
FROM ${BASE} as prod | ||
|
||
LABEL org.opencontainers.image.title="Python 3.11 image with pynautobot" | ||
LABEL org.opencontainers.image.base.name="ghcr.io/rackerlabs/understack/ironic-to-nautobot-sync-python3.11.8" | ||
LABEL org.opencontainers.image.source=https://github.com/rackerlabs/understack | ||
|
||
|
||
ENV PATH="/opt/venv/bin:$PATH" | ||
COPY --from=builder /opt/venv /opt/venv | ||
|
||
WORKDIR /app | ||
|
||
USER $APP_USER | ||
|
||
COPY --chown=${APP_USER}:${APP_GROUP} code/ /app | ||
CMD ["python", "/app/main.py"] |
2 changes: 2 additions & 0 deletions
2
argo-workflows/ironic-to-nautobot-sync/containers/requirements.txt
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,2 @@ | ||
requests==2.31.0 | ||
pynautobot==2.1.1 |
68 changes: 68 additions & 0 deletions
68
argo-workflows/ironic-to-nautobot-sync/sensors/ironic-to-nautobot-sensor.yaml
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,68 @@ | ||
--- | ||
apiVersion: argoproj.io/v1alpha1 | ||
kind: Sensor | ||
metadata: | ||
finalizers: | ||
- sensor-controller | ||
labels: | ||
argocd.argoproj.io/instance: argo-events | ||
name: ironic-node-update | ||
namespace: argo-events | ||
spec: | ||
dependencies: | ||
- eventName: openstack | ||
eventSourceName: openstack-amqp | ||
name: ironic-dep | ||
transform: | ||
jq: ".body[\"oslo.message\"] | fromjson" | ||
filters: | ||
dataLogicalOperator: "and" | ||
data: | ||
- path: "event_type" | ||
type: "string" | ||
value: | ||
- "baremetal.node.update.end" | ||
template: | ||
serviceAccountName: operate-workflow-sa | ||
triggers: | ||
- template: | ||
name: ironic-node-update-trigger | ||
k8s: | ||
operation: create | ||
parameters: | ||
- dest: spec.arguments.parameters.0.value | ||
src: | ||
dataKey: payload.ironic_object\.data.uuid | ||
dependencyName: ironic-dep | ||
- dest: spec.arguments.parameters.1.value | ||
src: | ||
dataKey: payload.ironic_object\.data.provision_state | ||
dependencyName: ironic-dep | ||
source: | ||
resource: | ||
apiVersion: argoproj.io/v1alpha1 | ||
kind: Workflow | ||
metadata: | ||
generateName: ironic-node-update- | ||
spec: | ||
arguments: | ||
parameters: | ||
- name: device_uuid | ||
value: Device UUID | ||
- name: provision_state | ||
value: Ironic Provision state | ||
entrypoint: start | ||
serviceAccountName: workflow | ||
templates: | ||
- name: start | ||
steps: | ||
- - name: synchronize-provision-state-to-nautobot | ||
templateRef: | ||
name: synchronize-provision-state-to-nautobot | ||
template: synchronize-state | ||
arguments: | ||
parameters: | ||
- name: device_uuid | ||
value: "{{workflow.parameters.device_uuid}}" | ||
- name: provision_state | ||
value: "{{workflow.parameters.provision_state}}" |
35 changes: 35 additions & 0 deletions
35
argo-workflows/ironic-to-nautobot-sync/workflowtemplates/sync.yaml
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,35 @@ | ||
apiVersion: argoproj.io/v1alpha1 | ||
metadata: | ||
name: synchronize-provision-state-to-nautobot | ||
kind: WorkflowTemplate | ||
spec: | ||
arguments: | ||
parameters: | ||
- name: device_uuid | ||
value: "{}" | ||
- name: provision_state | ||
value: "{}" | ||
templates: | ||
- name: synchronize-state | ||
container: | ||
image: ghcr.io/rackerlabs/understack/ironic-to-nautobot-sync:latest | ||
command: | ||
- python | ||
- /app/main.py | ||
args: | ||
- --device_uuid | ||
- "{{workflow.parameters.device_uuid}}" | ||
- --provisioning-state | ||
- "{{workflow.parameters.provision_state}}" | ||
volumeMounts: | ||
- mountPath: /etc/nb-token/ | ||
name: nb-token | ||
readOnly: true | ||
inputs: | ||
parameters: | ||
- name: device_uuid | ||
- name: provision_state | ||
volumes: | ||
- name: nb-token | ||
secret: | ||
secretName: nautobot-token |