Skip to content

Commit 791b084

Browse files
committed
feat: add locationType sync to operator
1 parent fde45af commit 791b084

File tree

13 files changed

+443
-5
lines changed

13 files changed

+443
-5
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../schema/location-types.schema.json

go/nautobotop/api/v1alpha1/nautobot_types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type NautobotSpec struct {
3232
NautobotSecretRef SecretKeySelector `json:"nautobotSecretRef,omitempty"`
3333
NautobotServiceRef ServiceSelector `json:"nautobotServiceRef,omitempty"`
3434
DeviceTypesRef []ConfigMapRef `json:"deviceTypeRef,omitempty"`
35+
LocationTypesRef []ConfigMapRef `json:"locationTypesRef,omitempty"`
3536
}
3637

3738
// NautobotStatus defines the observed state of Nautobot.

go/nautobotop/api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

go/nautobotop/config/crd/bases/sync.rax.io_nautobots.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,35 @@ spec:
6868
- name
6969
type: object
7070
type: array
71+
locationTypesRef:
72+
items:
73+
description: ConfigMapRef defines a reference to a specific ConfigMap
74+
properties:
75+
configMapSelector:
76+
description: The name of the ConfigMap resource being referred
77+
to
78+
properties:
79+
key:
80+
description: The key in the ConfigMap data
81+
type: string
82+
name:
83+
description: The name of the ConfigMap
84+
minLength: 1
85+
type: string
86+
namespace:
87+
description: The namespace where the ConfigMap resides
88+
type: string
89+
required:
90+
- name
91+
type: object
92+
name:
93+
description: Name of this config set (logical name)
94+
type: string
95+
required:
96+
- configMapSelector
97+
- name
98+
type: object
99+
type: array
71100
nautobotSecretRef:
72101
properties:
73102
name:

go/nautobotop/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.24.0
44

55
require (
66
github.com/charmbracelet/log v0.4.2
7-
github.com/nautobot/go-nautobot/v3 802218866be0
7+
github.com/nautobot/go-nautobot/v3 v3.0.0-20241004125816-802218866be0
88
github.com/onsi/ginkgo/v2 v2.22.0
99
github.com/onsi/gomega v1.36.1
1010
github.com/samber/lo v1.52.0
@@ -114,4 +114,4 @@ require (
114114
sigs.k8s.io/yaml v1.4.0 // indirect
115115
)
116116

117-
replace github.com/nautobot/go-nautobot/v3 => github.com/abhimanyu003/go-nautobot/v3 v3.0.0-beta
117+
replace github.com/nautobot/go-nautobot/v3 => github.com/abhimanyu003/go-nautobot/v3 v3.0.1

go/nautobotop/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
cel.dev/expr v0.19.1 h1:NciYrtDRIR0lNCnH1LFJegdjspNx9fI59O7TWcua/W4=
22
cel.dev/expr v0.19.1/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
3-
github.com/abhimanyu003/go-nautobot/v3 v3.0.0-beta h1:lsRCn6JkSKHfedSpqt7MOgSkJHwEmjISSb2dg5Zs/ks=
4-
github.com/abhimanyu003/go-nautobot/v3 v3.0.0-beta/go.mod h1:syPUSxlp3KXMTLetxOBvWPz2+JHfQFaQUxYWmvw9Ljo=
3+
github.com/abhimanyu003/go-nautobot/v3 v3.0.1 h1:ajG1GbYKSa91Mk+3EP6ucsN4+jctAE/cYCIQgqKl4tY=
4+
github.com/abhimanyu003/go-nautobot/v3 v3.0.1/go.mod h1:syPUSxlp3KXMTLetxOBvWPz2+JHfQFaQUxYWmvw9Ljo=
55
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
66
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
77
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=

go/nautobotop/helm/crds/clients.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,35 @@ spec:
6868
- name
6969
type: object
7070
type: array
71+
locationTypesRef:
72+
items:
73+
description: ConfigMapRef defines a reference to a specific ConfigMap
74+
properties:
75+
configMapSelector:
76+
description: The name of the ConfigMap resource being referred
77+
to
78+
properties:
79+
key:
80+
description: The key in the ConfigMap data
81+
type: string
82+
name:
83+
description: The name of the ConfigMap
84+
minLength: 1
85+
type: string
86+
namespace:
87+
description: The namespace where the ConfigMap resides
88+
type: string
89+
required:
90+
- name
91+
type: object
92+
name:
93+
description: Name of this config set (logical name)
94+
type: string
95+
required:
96+
- configMapSelector
97+
- name
98+
type: object
99+
type: array
71100
nautobotSecretRef:
72101
properties:
73102
name:

go/nautobotop/internal/controller/nautobot_controller.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ func (r *NautobotReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
6868
return ctrl.Result{}, client.IgnoreNotFound(err)
6969
}
7070

71+
// Aggregate device type data from all referenced ConfigMaps
72+
locationTypeMap, err := r.aggregateDeviceTypeDataFromConfigMap(ctx, nautobotCR.Spec.LocationTypesRef)
73+
if err != nil {
74+
log.Error(err, "failed to aggregate device type data from ConfigMaps")
75+
return ctrl.Result{}, err
76+
}
77+
7178
// Aggregate device type data from all referenced ConfigMaps
7279
deviceTypeMap, err := r.aggregateDeviceTypeDataFromConfigMap(ctx, nautobotCR.Spec.DeviceTypesRef)
7380
if err != nil {
@@ -105,6 +112,10 @@ func (r *NautobotReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
105112
nautobotURL := fmt.Sprintf("http://%s.%s.svc.cluster.local/api", nautobotCR.Spec.NautobotServiceRef.Name, nautobotCR.Spec.NautobotServiceRef.Namespace)
106113
nautobotClient := nbClient.NewNautobotClient(nautobotURL, username, token)
107114

115+
if err := r.syncLocationTypes(ctx, nautobotClient, locationTypeMap); err != nil {
116+
log.Error(err, "failed to sync device types")
117+
return ctrl.Result{}, err
118+
}
108119
if err := r.syncDeviceTypes(ctx, nautobotClient, deviceTypeMap); err != nil {
109120
log.Error(err, "failed to sync device types")
110121
return ctrl.Result{}, err
@@ -169,6 +180,21 @@ func (r *NautobotReconciler) syncDeviceTypes(ctx context.Context,
169180
return nil
170181
}
171182

183+
func (r *NautobotReconciler) syncLocationTypes(ctx context.Context,
184+
nautobotClient *nbClient.NautobotClient,
185+
locationType map[string]string,
186+
) error {
187+
log := logf.FromContext(ctx)
188+
189+
log.Info("syncing location types", "locationTypeCount", len(locationType))
190+
syncSvc := sync.NewLocationTypeSync(nautobotClient)
191+
if err := syncSvc.SyncAll(ctx, locationType); err != nil {
192+
return fmt.Errorf("failed to sync location types: %w", err)
193+
}
194+
195+
return nil
196+
}
197+
172198
// getAuthTokenFromSecretRef: this will fetch Nautobot auth token from the given refer.
173199
func (r *NautobotReconciler) getAuthTokenFromSecretRef(ctx context.Context, nautobotCR syncv1alpha1.Nautobot) (string, string, error) {
174200
var username, token string
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package dcim
2+
3+
import (
4+
"context"
5+
6+
"github.com/rackerlabs/understack/go/nautobotop/internal/nautobot/client"
7+
8+
"github.com/charmbracelet/log"
9+
nb "github.com/nautobot/go-nautobot/v3"
10+
"github.com/rackerlabs/understack/go/nautobotop/internal/nautobot/helpers"
11+
)
12+
13+
type LocationTypeService struct {
14+
client *client.NautobotClient
15+
}
16+
17+
func NewLocationTypeService(nautobotClient *client.NautobotClient) *LocationTypeService {
18+
return &LocationTypeService{
19+
client: nautobotClient,
20+
}
21+
}
22+
23+
func (s *LocationTypeService) Create(ctx context.Context, req nb.LocationTypeRequest) (*nb.LocationType, error) {
24+
locationType, resp, err := s.client.APIClient.DcimAPI.DcimLocationTypesCreate(ctx).LocationTypeRequest(req).Execute()
25+
if err != nil {
26+
bodyString := helpers.ReadResponseBody(resp)
27+
s.client.AddReport("createNewLocationType", "failed to create", "model", req.Name, "error", err.Error(), "response_body", bodyString)
28+
return nil, err
29+
}
30+
log.Info("CreateLocationType", "created device type", locationType.Name)
31+
return locationType, nil
32+
}
33+
34+
func (s *LocationTypeService) GetByName(ctx context.Context, name string) nb.LocationType {
35+
list, resp, err := s.client.APIClient.DcimAPI.DcimLocationTypesList(ctx).Depth(10).Name([]string{name}).Execute()
36+
if err != nil {
37+
bodyString := helpers.ReadResponseBody(resp)
38+
s.client.AddReport("GetLocationTypeByName", "failed to get", "name", name, "error", err.Error(), "response_body", bodyString)
39+
return nb.LocationType{}
40+
}
41+
if list == nil || len(list.Results) == 0 {
42+
return nb.LocationType{}
43+
}
44+
if list.Results[0].Id == nil {
45+
return nb.LocationType{}
46+
}
47+
return list.Results[0]
48+
}
49+
50+
func (s *LocationTypeService) ListAll(ctx context.Context) []nb.LocationType {
51+
ids := s.client.GetChangeObjectIDS(ctx, "dcim.locationtype")
52+
list, resp, err := s.client.APIClient.DcimAPI.DcimLocationTypesList(ctx).Id(ids).Depth(10).Execute()
53+
if err != nil {
54+
bodyString := helpers.ReadResponseBody(resp)
55+
s.client.AddReport("ListAllLocationTypes", "failed to list", "error", err.Error(), "response_body", bodyString)
56+
return []nb.LocationType{}
57+
}
58+
if list == nil || len(list.Results) == 0 {
59+
return []nb.LocationType{}
60+
}
61+
if list.Results[0].Id == nil {
62+
return []nb.LocationType{}
63+
}
64+
65+
return list.Results
66+
}
67+
68+
func (s *LocationTypeService) Update(ctx context.Context, id string, req nb.LocationTypeRequest) (*nb.LocationType, error) {
69+
locationType, resp, err := s.client.APIClient.DcimAPI.DcimLocationTypesUpdate(ctx, id).LocationTypeRequest(req).Execute()
70+
if err != nil {
71+
bodyString := helpers.ReadResponseBody(resp)
72+
s.client.AddReport("UpdateLocationType", "failed to update UpdateLocationType", "id", id, "model", req.Name, "error", err.Error(), "response_body", bodyString)
73+
return nil, err
74+
}
75+
log.Info("successfully updated device type", "id", id, "model", locationType.GetName())
76+
return locationType, nil
77+
}
78+
79+
func (s *LocationTypeService) Destroy(ctx context.Context, id string) error {
80+
resp, err := s.client.APIClient.DcimAPI.DcimLocationTypesDestroy(ctx, id).Execute()
81+
if err != nil {
82+
bodyString := helpers.ReadResponseBody(resp)
83+
s.client.AddReport("DestroyLocationType", "failed to destroy", "id", id, "error", err.Error(), "response_body", bodyString)
84+
return err
85+
}
86+
return nil
87+
}

go/nautobotop/internal/nautobot/dcim/templates/power_port.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func (s *PowerPortTemplateService) ListByDeviceType(ctx context.Context, deviceT
2626

2727
// Define the API call function for this specific endpoint
2828
apiCall := func(ctx context.Context, batchIds []string) ([]nb.PowerPortTemplate, *http.Response, error) {
29-
list, resp, err := s.client.APIClient.DcimAPI.DcimPowerPortTemplatesList(ctx).Id(batchIds).Depth(2).DeviceType([]string{deviceTypeID}).Execute()
29+
list, resp, err := s.client.APIClient.DcimAPI.DcimPowerPortTemplatesList(ctx).Id(batchIds).Depth(1).DeviceType([]string{deviceTypeID}).Execute()
3030
if err != nil {
3131
return nil, resp, err
3232
}

0 commit comments

Comments
 (0)