Skip to content

Commit

Permalink
Merge pull request #195 from rackerlabs/trigger-undersync-single-switch
Browse files Browse the repository at this point in the history
feat:  workflow to undersync individual switches
  • Loading branch information
cardoe authored Aug 5, 2024
2 parents bc34f07 + eee55e9 commit cddba5b
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
apiVersion: argoproj.io/v1alpha1
metadata:
name: undersync-switch
kind: WorkflowTemplate
spec:
entrypoint: undersync-switch
serviceAccountName: workflow
templates:
- name: undersync-switch
container:
image: ghcr.io/rackerlabs/understack/ironic-nautobot-client:latest
command:
- undersync-switch
args:
- --switch_uuids
- "{{workflow.parameters.switch_uuids}}"
- --dry-run
- "{{workflow.parameters.dry_run}}"
- --force
- "{{workflow.parameters.force}}"
volumeMounts:
- mountPath: /etc/nb-token/
name: nb-token
readOnly: true
- mountPath: /etc/undersync/
name: undersync-token
readOnly: true
inputs:
parameters:
- name: switch_uuids
- name: force
- name: dry_run
volumes:
- name: nb-token
secret:
secretName: nautobot-token
- name: undersync-token
secret:
secretName: undersync-token
1 change: 1 addition & 0 deletions python/understack-workflows/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ synchronize-interfaces = "understack_workflows.main.synchronize_interfaces:main"
synchronize-obm-creds = "understack_workflows.main.synchronize_obm_creds:main"
synchronize-server = "understack_workflows.main.synchronize_server:main"
sync-nautobot-interfaces = "understack_workflows.main.sync_nautobot_interfaces:main"
undersync-switch = "understack_workflows.main.undersync_switch:main"

[tool.setuptools.packages.find]
# avoid packaging up our tests
Expand Down
14 changes: 14 additions & 0 deletions python/understack-workflows/understack_workflows/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import logging
import os
import pathlib
from functools import partial

import sushy

Expand Down Expand Up @@ -35,6 +36,19 @@ def arg_parser(name):
return parser


def boolean_args(val):
normalised = str(val).upper()
if normalised in ["YES", "TRUE", "T", "1"]:
return True
elif normalised in ["NO", "FALSE", "F", "N", "0"]:
return False
else:
raise argparse.ArgumentTypeError("boolean expected")


comma_list_args = partial(str.split, sep=",")


def credential(subpath, item):
ref = pathlib.Path("/etc").joinpath(subpath).joinpath(item)
with ref.open() as f:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import argparse
import os
import sys

from understack_workflows.helpers import boolean_args
from understack_workflows.helpers import comma_list_args
from understack_workflows.helpers import credential
from understack_workflows.helpers import setup_logger
from understack_workflows.undersync.client import Undersync


def call_undersync(args, switches):
undersync_token = credential("undersync", "token")
if not undersync_token:
logger.error("Please provide auth token for Undersync.")
sys.exit(1)
undersync = Undersync(undersync_token)

try:
logger.debug(f"Syncing switches: {switches} {args.dry_run=} {args.force=}")
return undersync.sync_devices(switches, dry_run=args.dry_run, force=args.force)
except Exception as error:
logger.error(error)
sys.exit(2)


def argument_parser():
parser = argparse.ArgumentParser(
prog=os.path.basename(__file__),
description="Trigger undersync run for a set of switches.",
)
parser.add_argument(
"--switch_uuids",
type=comma_list_args,
required=True,
help="Comma separated list of UUIDs of the switches to Undersync",
)
parser.add_argument(
"--force",
type=boolean_args,
help="Call Undersync's force endpoint",
required=False,
)
parser.add_argument(
"--dry-run",
type=boolean_args,
help="Call Undersync's dry-run endpoint",
required=False,
)

return parser


def main():
"""Requests an Undersync run on a pair of switches."""
args = argument_parser().parse_args()

response = call_undersync(args, args.switch_uuids)
logger.info(f"Undersync returned: {response.json()}")


logger = setup_logger(__name__)
if __name__ == "__main__":
main()
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from functools import cached_property

import requests


class Undersync:
def __init__(
self,
auth_token: str,
api_url="http://undersync-service.undersync.svc.cluster.local:8080",
) -> None:
self.token = auth_token
self.api_url = api_url

def sync_devices(self, switch_uuids: str | list[str], force=False, dry_run=False):
if isinstance(switch_uuids, list):
switch_uuids = ",".join(switch_uuids)

if dry_run:
return self.dry_run(switch_uuids)
elif force:
return self.force(switch_uuids)
else:
return self.sync(switch_uuids)

@cached_property
def client(self):
session = requests.Session()
session.headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {self.token}",
}
return session

def sync(self, uuids: str) -> requests.Response:
response = self.client.post(f"{self.api_url}/v1/devices/{uuids}/sync")
response.raise_for_status()
return response

def dry_run(self, uuids: str) -> requests.Response:
response = self.client.post(f"{self.api_url}/v1/devices/{uuids}/dry-run")
response.raise_for_status()
return response

def force(self, uuids: str) -> requests.Response:
response = self.client.post(f"{self.api_url}/v1/devices/{uuids}/force")
response.raise_for_status()
return response

0 comments on commit cddba5b

Please sign in to comment.