Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .typos.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ extend-exclude = [
"schema/argo-workflows.json",
"python/understack-workflows/tests/json_samples/",
"containers/*/patches",
"go.mod"
"go.mod",
"ansible/roles/statuses/defaults/main.yaml",
]

[default]
Expand All @@ -19,3 +20,4 @@ extend-ignore-identifiers-re = [
HPE = "HPE"
fo = "fo"
sme = "sme"
4caf50 = "4caf50"
52 changes: 52 additions & 0 deletions ansible/playbooks/nautobot-initial-setup.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
- name: Initial setup of a Nautobot Dev Instance
connection: local
hosts: nautobot
gather_facts: false

# The goal after this playbook runs is to have a set of devices that can
# be tested against. For a Device to be defined in Nautobot you must
# first have a Device Role, a Device Type, and a Rack. For a Device Type
# to be defined you must first have a Manufacturer. For a Rack to be
# defined you must first have a Site. The Rackspace plugin to read
# data from CORE and Location Manager can provide some of these but
# that involves enabling Jobs from our plugin first. To be able to
# run our Jobs we need to populate some Secrets as well.
#
# To visualized linearly we need to instanitate the following:
# - Jobs
# - Secrets
# - Locations
# - Racks
# - Tenants
# - Device Role
# - Manufacturer
# - Device Type
# - Devices

pre_tasks:
- name: Ensure nautobot is up and responding
ansible.builtin.uri:
url: "{{ nautobot_url }}/health/"
method: GET
validate_certs: false
register: nautobot_up_check
until: nautobot_up_check.status == 200
retries: 24 # Retries for 24 * 5 seconds = 120 seconds = 2 minutes
delay: 5 # Every 5 seconds
check_mode: false

roles:
- role: permissions
tags: permissions
- role: jobs
- role: secrets
- role: git_repos
- role: location_types
- role: locations
- role: roles
- role: statuses
- role: custom_fields
- role: computed_fields
- role: platforms
- role: relationships
17 changes: 17 additions & 0 deletions ansible/roles/computed_fields/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# computed fields dynamically create a new field pulling from existing data sources already in Nautobot,

In your variables you'll need to define something like:

```yaml
computed_fields_data:
- key: urn
display: "Device URN"
content_type: dcim.device
label: "Device URN"
description: "A string representing the URN for a device"
template: "{%- if obj.serial and obj.role and obj.location and obj.device_type and obj.device_type.manufacturer %}\n {%- set role = obj.role.name | lower | replace(\" \", \"-\") -%}\n {%- set loc = obj.location.name | lower -%}\n {%- set manufacturer = obj.device_type.manufacturer.name | lower -%}\n {%- set serial = obj.serial | lower -%}\n {%- set partition = \"UC_PARTITION\" | settings_or_config -%}\nurn:rax:undercloud:{{ partition }}:nautobot:{{ role }}:{{ loc }}:{{ manufacturer }}-{{ serial }} {%- endif %}"
weight: 100
advanced_ui: false
```

Where the `key` is the unique slug.
2 changes: 2 additions & 0 deletions ansible/roles/computed_fields/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
computed_fields_data: []
27 changes: 27 additions & 0 deletions ansible/roles/computed_fields/tasks/computed_fields.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---

- name: Check if compute field exists
ansible.builtin.uri:
url: "{{ nautobot_url }}/api/extras/computed-fields/?key={{ item.key }}"
method: GET
body_format: json
headers:
Accept: application/json; version={{ nautobot_api_version }}
Authorization: "Token {{ nautobot_token }}"
register: _computed_field
check_mode: false

- name: Create/update computed fields
ansible.builtin.uri:
url: "{{ nautobot_url }}/api/extras/computed-fields/{{ url_append }}"
method: "{{ method }}"
headers:
Accept: application/json; version={{ nautobot_api_version }}
Authorization: "Token {{ nautobot_token }}"
body_format: json
body: "{{ item }}"
status_code: "{{ status_code }}"
vars:
url_append: "{{ _computed_field.json.results[0].id + '/' if _computed_field.json.count == 1 else '' }}"
method: "{{ 'PATCH' if _computed_field.json.count == 1 else 'POST' }}"
status_code: "{{ 200 if _computed_field.json.count == 1 else 201 }}"
5 changes: 5 additions & 0 deletions ansible/roles/computed_fields/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---

- name: Define computed fields
ansible.builtin.include_tasks: computed_fields.yml
loop: "{{ computed_fields_data }}"
107 changes: 107 additions & 0 deletions ansible/roles/custom_field_choices/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
---

custom_field_choices_data:
- value: active
weight: 100
custom_field: ironic_provision_state
state: present
- value: adopting
weight: 100
custom_field: ironic_provision_state
state: present
- value: available
weight: 100
custom_field: ironic_provision_state
state: present
- value: cleaning
weight: 100
custom_field: ironic_provision_state
state: present
- value: clean wait
weight: 100
custom_field: ironic_provision_state
state: present
- value: deleting
weight: 100
custom_field: ironic_provision_state
state: present
- value: deploy failed
weight: 100
custom_field: ironic_provision_state
state: present
- value: deploying
weight: 100
custom_field: ironic_provision_state
state: present
- value: enroll
weight: 100
custom_field: ironic_provision_state
state: present
- value: error
weight: 100
custom_field: ironic_provision_state
state: present
- value: inspect failed
weight: 100
custom_field: ironic_provision_state
state: present
- value: inspecting
weight: 100
custom_field: ironic_provision_state
state: present
- value: inspect wait
weight: 100
custom_field: ironic_provision_state
state: present
- value: manageable
weight: 100
custom_field: ironic_provision_state
state: present
- value: rescue
weight: 100
custom_field: ironic_provision_state
state: present
- value: rescue failed
weight: 100
custom_field: ironic_provision_state
state: present
- value: rescue wait
weight: 100
custom_field: ironic_provision_state
state: present
- value: rescuing
weight: 100
custom_field: ironic_provision_state
state: present
- value: rescuingrescue wait
weight: 100
custom_field: ironic_provision_state
state: present
- value: service failed
weight: 100
custom_field: ironic_provision_state
state: present
- value: service wait
weight: 100
custom_field: ironic_provision_state
state: present
- value: servicing
weight: 100
custom_field: ironic_provision_state
state: present
- value: unrescue failed
weight: 100
custom_field: ironic_provision_state
state: present
- value: unrescuing
weight: 100
custom_field: ironic_provision_state
state: present
- value: verifying
weight: 100
custom_field: ironic_provision_state
state: present
- value: wait call-back
weight: 100
custom_field: ironic_provision_state
state: present
12 changes: 12 additions & 0 deletions ansible/roles/custom_field_choices/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---

- name: Create Custom Field Choices
networktocode.nautobot.custom_field_choice:
url: "{{ nautobot_url }}"
token: "{{ nautobot_token }}"
value: "{{ item.value }}"
weight: "{{ item.weight }}"
custom_field: "{{ item.custom_field }}"
state: present

loop: "{{ custom_field_choices_data }}"
57 changes: 57 additions & 0 deletions ansible/roles/custom_fields/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
- name: Create Custom Field Chassis MAC Address
networktocode.nautobot.custom_field:
state: present
url: "{{ nautobot_url }}"
token: "{{ nautobot_token }}"
description: MAC address advertised to LLDP neighbors (for switches only)
label: Chassis MAC Address
type: text
key: chassis_mac_address
required: false
weight: 100
content_types: dcim.device
filter_logic: exact
validation_regex: ^[0-9A-F][0-9A-F](:[0-9A-F][0-9A-F]){5}$

- name: Create Custom Field DHCP Relay IPv4 Address
networktocode.nautobot.custom_field:
state: present
url: "{{ nautobot_url }}"
token: "{{ nautobot_token }}"
description: >-
For certain interface Roles, configure a "DHCP Helper" service on the
router to forward DHCP requests from locally-connected clients to the
DHCP server specified by this option. The value is an IPv4 address
without the /prefixlen.
label: DHCP Relay IPv4 Address
type: text
key: dhcp_relay_ipv4_address
required: false
weight: 100
content_types:
- dcim.interface
- vni_custom_model.ucvni
validation_regex: ^\d+\.\d+\.\d+\.\d+$
filter_logic: exact

- name: Create Custom Field Tenant VLAN ID
networktocode.nautobot.custom_field:
state: present
url: "{{ nautobot_url }}"
token: "{{ nautobot_token }}"
description: >-
VLAN ID visible to the Tenant, used in the dot1q tag when this VNI
appears on a trunk port. Normally different to the actual VLAN created
on the switch - we use VLAN translation to gives the tenant a consistent
VLAN ID across the whole fabric.
label: Tenant VLAN ID
type: integer
key: tenant_vlan_id
required: false
weight: 100
content_types:
- vni_custom_model.ucvni
validation_minimum: 1
validation_maximum: 4096
filter_logic: exact
15 changes: 15 additions & 0 deletions ansible/roles/git_repos/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Adding Git Repos

In your variables you'll need to define something like:

```yaml
nb_git_repos:
device_types:
name: Device Types
remote_url: https://github.com/RSS-Engineering/undercloud-nautobot-device-types.git
branch: main
secrets_group: gh_dev_type_pat
```
Where the `key` is the unique slug and the `secrets_group` is the reference to
a `secrets_group` you've defined in the variable `nb_secrets_groups`.
2 changes: 2 additions & 0 deletions ansible/roles/git_repos/defaults/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
git_repos_nb_git_repos: {}
28 changes: 28 additions & 0 deletions ansible/roles/git_repos/tasks/git_repo_def.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---

- name: Check if git repo exists
ansible.builtin.uri:
url: "{{ nautobot_url }}/api/extras/git-repositories/?slug={{ item.key }}"
method: GET
body_format: json
headers:
Accept: "application/json; version={{ nautobot_api_version }}"
Authorization: "Token {{ nautobot_token }}"
register: _secret
check_mode: false

- name: Create/update secret group association
ansible.builtin.uri:
url: "{{ nautobot_url }}/api/extras/git-repositories/{{ url_append }}"
method: "{{ method }}"
headers:
Accept: "application/json; version={{ nautobot_api_version }}"
Authorization: "Token {{ nautobot_token }}"
body_format: json
body: "{{ item.value | combine({'slug': item.key}) }}"
status_code: "{{ status_code }}"
register: _secret_create
vars:
url_append: "{{ _secret.json.results[0].id + '/' if _secret.json.count == 1 else '' }}"
method: "{{ 'PATCH' if _secret.json.count == 1 else 'POST' }}"
status_code: "{{ 200 if _secret.json.count == 1 else 201 }}"
5 changes: 5 additions & 0 deletions ansible/roles/git_repos/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---

- name: Define git repos
ansible.builtin.include_tasks: git_repo_def.yml
loop: "{{ git_repos_nb_git_repos | dict2items }}"
23 changes: 23 additions & 0 deletions ansible/roles/jobs/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---

- name: "Lookup Rackspace Jobs"
ansible.builtin.uri:
url: "{{ nautobot_url }}/api/extras/jobs/"
method: GET
headers:
Authorization: "Token {{ nautobot_token }}"
register: rackspace_jobs
check_mode: false

- name: "Enable Rackspace Jobs"
ansible.builtin.uri:
url: "{{ nautobot_url }}/api/extras/jobs/{{ item.id }}/"
method: PATCH
headers:
Authorization: "Token {{ nautobot_token }}"
body_format: json
body:
enabled: true
loop: "{{ rackspace_jobs.json | community.general.json_query(rackspace_grouping_query) }}"
vars:
rackspace_grouping_query: "results[?grouping=='Rackspace' || grouping=='ServiceNow Sync Jobs']"
Loading