Skip to content

Commit d3dc3af

Browse files
authored
Merge pull request #318 from rackerlabs/workflow-auth
feat: utilize clouds.yaml for authentication in workflows
2 parents df6be8e + f7c6477 commit d3dc3af

File tree

14 files changed

+89
-145
lines changed

14 files changed

+89
-145
lines changed

python/understack-workflows/understack_workflows/create_node.py

Lines changed: 0 additions & 27 deletions
This file was deleted.

python/understack-workflows/understack_workflows/ironic/client.py

Lines changed: 11 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,21 @@
1-
from ironicclient import client as iclient
2-
from keystoneauth1 import session
3-
from keystoneauth1.identity import v3
1+
from understack_workflows.openstack.client import get_ironic_client
42

53

64
class IronicClient:
75
def __init__(
86
self,
9-
svc_url: str,
10-
username: str,
11-
password: str,
12-
auth_url: str,
13-
tenant_name: str,
147
) -> None:
158
"""Initialize our ironicclient wrapper."""
16-
self.svc_url = svc_url
17-
self.username = username
18-
self.password = password
19-
self.auth_url = auth_url
20-
self.tenant_name = tenant_name
219
self.logged_in = False
22-
self.os_ironic_api_version = "1.82"
2310

2411
def login(self):
25-
auth = v3.Password(
26-
auth_url=self.auth_url,
27-
username=self.username,
28-
password=self.password,
29-
project_name=self.tenant_name,
30-
project_domain_name="Default",
31-
user_domain_name="Default",
32-
)
33-
insecure_ssl = True
34-
sess = session.Session(
35-
auth=auth, verify=(not insecure_ssl), app_name="nautobot"
36-
)
37-
self.client = iclient.Client(
38-
1,
39-
endpoint_override=self.svc_url,
40-
session=sess,
41-
insecure=insecure_ssl,
42-
)
43-
self.client.negotiate_api_version()
12+
self.client = get_ironic_client()
4413
self.logged_in = True
4514

4615
def create_node(self, node_data: dict):
4716
self._ensure_logged_in()
4817

49-
return self.client.node.create(
50-
os_ironic_api_version=self.os_ironic_api_version, **node_data
51-
)
18+
return self.client.node.create(**node_data)
5219

5320
def list_nodes(self):
5421
self._ensure_logged_in()
@@ -59,35 +26,36 @@ def get_node(self, node_ident: str, fields: list[str] | None = None):
5926
self._ensure_logged_in()
6027

6128
return self.client.node.get(
62-
node_ident, fields, os_ironic_api_version=self.os_ironic_api_version
29+
node_ident,
30+
fields,
6331
)
6432

6533
def update_node(self, node_id, patch):
6634
self._ensure_logged_in()
6735

6836
return self.client.node.update(
69-
node_id, patch, os_ironic_api_version=self.os_ironic_api_version
37+
node_id,
38+
patch,
7039
)
7140

7241
def create_port(self, port_data: dict):
7342
self._ensure_logged_in()
7443

75-
return self.client.port.create(
76-
os_ironic_api_version=self.os_ironic_api_version, **port_data
77-
)
44+
return self.client.port.create(**port_data)
7845

7946
def update_port(self, port_id: str, patch: list):
8047
self._ensure_logged_in()
8148

8249
return self.client.port.update(
83-
port_id, patch, os_ironic_api_version=self.os_ironic_api_version
50+
port_id,
51+
patch,
8452
)
8553

8654
def delete_port(self, port_id: str):
8755
self._ensure_logged_in()
8856

8957
return self.client.port.delete(
90-
port_id, os_ironic_api_version=self.os_ironic_api_version
58+
port_id,
9159
)
9260

9361
def list_ports(self, node_id: dict):

python/understack-workflows/understack_workflows/ironic/secrets.py

Lines changed: 0 additions & 20 deletions
This file was deleted.

python/understack-workflows/understack_workflows/main/sync_interfaces.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,7 @@ def main():
8585
nautobot_ports = get_nautobot_interfaces(nautobot, device_id)
8686

8787
# get Ironic Ports
88-
client = IronicClient(
89-
svc_url=os.environ["IRONIC_SVC_URL"],
90-
username=os.environ["IRONIC_USERNAME"],
91-
password=os.environ["IRONIC_PASSWORD"],
92-
auth_url=os.environ["IRONIC_AUTH_URL"],
93-
tenant_name=os.environ["IRONIC_TENANT"],
94-
)
88+
client = IronicClient()
9589

9690
logger.info("Fetching Ironic Ports ...")
9791
ironic_ports = client.list_ports(device_id)

python/understack-workflows/understack_workflows/main/sync_keystone.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@
33
import uuid
44
from enum import StrEnum
55

6-
import openstack
7-
from openstack.connection import Connection
8-
96
from understack_workflows.domain import DefaultDomain
107
from understack_workflows.domain import domain_id
118
from understack_workflows.helpers import credential
129
from understack_workflows.helpers import parser_nautobot_args
1310
from understack_workflows.helpers import setup_logger
1411
from understack_workflows.nautobot import Nautobot
12+
from understack_workflows.openstack.client import Connection
13+
from understack_workflows.openstack.client import get_openstack_client
1514

1615
logger = setup_logger(__name__, level=logging.INFO)
1716

@@ -123,7 +122,7 @@ def do_action(
123122
def main():
124123
args = argument_parser().parse_args()
125124

126-
conn = openstack.connect(cloud=args.os_cloud)
125+
conn = get_openstack_client(cloud=args.os_cloud)
127126
nb_token = args.nautobot_token or credential("nb-token", "token")
128127
nautobot = Nautobot(args.nautobot_url, nb_token, logger=logger)
129128

python/understack-workflows/understack_workflows/main/sync_obm_creds.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from understack_workflows.helpers import credential
88
from understack_workflows.helpers import setup_logger
99
from understack_workflows.ironic.client import IronicClient
10-
from understack_workflows.ironic.secrets import read_secret
1110
from understack_workflows.node_configuration import IronicNodeConfiguration
1211

1312
logger = setup_logger(__name__)
@@ -20,13 +19,7 @@ def main():
2019
)
2120

2221
logger.info("Pushing device new node to Ironic.")
23-
client = IronicClient(
24-
svc_url=read_secret("IRONIC_SVC_URL"),
25-
username=read_secret("IRONIC_USERNAME"),
26-
password=read_secret("IRONIC_PASSWORD"),
27-
auth_url=read_secret("IRONIC_AUTH_URL"),
28-
tenant_name=read_secret("IRONIC_TENANT"),
29-
)
22+
client = IronicClient()
3023

3124
interface_update_event = json.loads(sys.argv[1])
3225
logger.debug(f"Received: {interface_update_event}")

python/understack-workflows/understack_workflows/main/sync_server.py

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
from understack_workflows.helpers import setup_logger
88
from understack_workflows.ironic.client import IronicClient
9-
from understack_workflows.ironic.secrets import read_secret
109
from understack_workflows.node_configuration import IronicNodeConfiguration
1110

1211
logger = setup_logger(__name__)
@@ -26,16 +25,6 @@ def get_args():
2625
return json.loads(sys.argv[1])
2726

2827

29-
def get_ironic_client():
30-
return IronicClient(
31-
svc_url=read_secret("IRONIC_SVC_URL"),
32-
username=read_secret("IRONIC_USERNAME"),
33-
password=read_secret("IRONIC_PASSWORD"),
34-
auth_url=read_secret("IRONIC_AUTH_URL"),
35-
tenant_name=read_secret("IRONIC_TENANT"),
36-
)
37-
38-
3928
def get_ironic_node(node, ironic_client):
4029
logger.debug(f"Checking if node UUID {node.uuid} exists in Ironic.")
4130

@@ -82,7 +71,7 @@ def main():
8271
update_data = interface_update_event["data"]
8372

8473
logger.info("Pushing device new node to Ironic.")
85-
ironic_client = get_ironic_client()
74+
ironic_client = IronicClient()
8675

8776
node = IronicNodeConfiguration.from_event(interface_update_event)
8877
ironic_node = get_ironic_node(node, ironic_client)

python/understack-workflows/understack_workflows/openstack/__init__.py

Whitespace-only changes.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"""helper to setup OpenStack clients."""
2+
3+
# attempt to prevent re-export
4+
import os as _os
5+
import sys as _sys
6+
from importlib import metadata as _meta
7+
8+
from ironicclient.client import Client as IronicClient
9+
from ironicclient.client import get_client as _get_ironic_client
10+
from openstack import config as _os_config
11+
from openstack.connection import Connection
12+
13+
try:
14+
_pkg_ver = _meta.version(__package__.split(".")[0])
15+
except Exception:
16+
_pkg_ver = "dev"
17+
18+
try:
19+
_prog_name = _os.path.basename(_sys.argv[0]) or "local"
20+
except Exception:
21+
_prog_name = "local"
22+
23+
24+
def _get_os_cloud_region(cloud=None, region_name=""):
25+
"""Returns a keystoneauth1 Session based on our clouds.yaml."""
26+
return _os_config.get_cloud_region(
27+
load_yaml_config=True,
28+
load_envvars=True,
29+
app_name=_prog_name,
30+
app_version=_pkg_ver,
31+
cloud=cloud,
32+
region_name=region_name,
33+
)
34+
35+
36+
def get_openstack_client(cloud=None, region_name="") -> Connection:
37+
"""Returns an OpenStackSDK Connection based on our clouds.yaml."""
38+
cloud_region = _get_os_cloud_region(cloud, region_name)
39+
40+
return Connection(config=cloud_region)
41+
42+
43+
def get_ironic_client(cloud=None, region_name="") -> IronicClient:
44+
"""Returns our Ironic Client wrapper configured from our clouds.yaml."""
45+
cloud_region = _get_os_cloud_region(cloud, region_name)
46+
client = _get_ironic_client(
47+
"1", session=cloud_region.get_session(), os_ironic_api_version="latest"
48+
)
49+
client.negotiate_api_version()
50+
return client
51+
52+
53+
__all__ = [
54+
"get_openstack_client",
55+
"get_ironic_client",
56+
]

workflows/argo-events/kustomization.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ resources:
99
- secrets/obm-creds.yaml
1010
- secrets/placeholder-obm-creds.yaml
1111
- secrets/operate-workflow-sa.token.yaml
12-
- secrets/production-ironic-for-argo-creds.yaml
1312
- secrets/nautobot-token.yaml
1413
- secrets/placeholder-obm-legacy-passwords.yaml
1514
- sensors/ironic-node-update.yaml

0 commit comments

Comments
 (0)