Skip to content

Commit ade6102

Browse files
Add VLANClaim model
1 parent b5527d1 commit ade6102

39 files changed

+2326
-23
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
**Disclaimer:** This project is currently under development and may change rapidly, including breaking changes. Use with caution in production environments.
44

5-
NetBox Operator extends the Kubernetes API by allowing users to manage NetBox resources – such as IP addresses and prefixes – directly through Kubernetes. This integration brings Kubernetes-native features like reconciliation, ensuring that network configurations are maintained automatically, thereby improving both efficiency and reliability.
5+
NetBox Operator extends the Kubernetes API by allowing users to manage NetBox resources – such as IP addresses, prefixes, and VLANs – directly through Kubernetes. This integration brings Kubernetes-native features like reconciliation, ensuring that network configurations are maintained automatically, thereby improving both efficiency and reliability.
66

77
## The Claim Model
88
The NetBox Operator implements a "Claim Model" which is also used in the Kubernetes PersistentVolumeClaims (PVCs).
99
In this case, instead of disk storage, NetBox Operator dynamically allocates network resources (Prefixes and IP Addresses) based on claims submitted via custom resources.
1010

1111
### Purpose
1212
This model ensures a declarative management of IP addressing and subnet allocation, with full NetBox integration.
13-
The users will create claims (PrefixClaims & IPAddressClaims), and the NetBox Operator will resolve them into actual Prefixes and IPAddresses within a designated parent prefix.
13+
The users will create claims (PrefixClaims, IPAddressClaims & VLANClaims), and the NetBox Operator will resolve them into actual Prefixes, IPAddresses and VLANs within a designated parent prefix or site.
1414

1515
![Figure 1: NetBox Operator High-Level Architecture](docs/netbox-operator-high-level-architecture.drawio.svg)
1616

@@ -53,7 +53,7 @@ To optionally access the NetBox UI:
5353

5454
## Testing NetBox Operator using samples
5555

56-
In the folder `config/samples/` you can find example manifests to create IpAddress, IpAddressClaim, Prefix, and PrefixClaim resources. Apply them to the cluster with `kubectl apply -f <file-name>` and use your favorite Kubernetes tools to display.
56+
In the folder `config/samples/` you can find example manifests to create IpAddress, IpAddressClaim, Prefix, PrefixClaim, and VLANClaim resources. Apply them to the cluster with `kubectl apply -f <file-name>` and use your favorite Kubernetes tools to display.
5757

5858
Example of assigning a Prefix using PrefixClaim:
5959

api/v1/vlan_types.go

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
Copyright 2024 Swisscom (Schweiz) AG.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1
18+
19+
import (
20+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
)
22+
23+
// VlanSpec defines the desired state of Vlan
24+
type VlanSpec struct {
25+
// The unique VLAN ID (VID)
26+
//+kubebuilder:validation:Required
27+
//+kubebuilder:validation:Minimum=1
28+
//+kubebuilder:validation:Maximum=4094
29+
//+kubebuilder:validation:XValidation:rule="self == oldSelf",message="Field 'vlanId' is immutable"
30+
VlanId int `json:"vlanId"`
31+
32+
// The desired name for the VLAN in NetBox
33+
//+kubebuilder:validation:Required
34+
Name string `json:"name"`
35+
36+
// The NetBox Site where this VLAN should exist
37+
//+kubebuilder:validation:Required
38+
Site string `json:"site"`
39+
40+
// The NetBox VLANGroup where this VLAN should be organized
41+
//+optional
42+
VlanGroup string `json:"vlanGroup,omitempty"`
43+
44+
// Description that should be added to the resource in NetBox
45+
//+optional
46+
Description string `json:"description,omitempty"`
47+
48+
// Comment that should be added to the resource in NetBox
49+
//+optional
50+
Comments string `json:"comments,omitempty"`
51+
52+
// The NetBox Custom Fields that should be added to the resource in NetBox
53+
//+optional
54+
CustomFields map[string]string `json:"customFields,omitempty"`
55+
56+
// Defines whether the Resource should be preserved in NetBox when the
57+
// Kubernetes Resource is deleted.
58+
//+optional
59+
PreserveInNetbox bool `json:"preserveInNetbox,omitempty"`
60+
}
61+
62+
// VlanStatus defines the observed state of Vlan
63+
type VlanStatus struct {
64+
// The NetBox internal database ID of the created/managed VLAN
65+
//+optional
66+
VlanId int64 `json:"id,omitempty"`
67+
68+
// The URL to the VLAN object in the NetBox UI
69+
//+optional
70+
VlanUrl string `json:"url,omitempty"`
71+
72+
// Conditions represent the latest available observations of an object's state
73+
//+optional
74+
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
75+
}
76+
77+
//+kubebuilder:object:root=true
78+
//+kubebuilder:subresource:status
79+
//+kubebuilder:storageversion
80+
//+kubebuilder:printcolumn:name="VLAN ID",type=integer,JSONPath=`.spec.vlanId`
81+
//+kubebuilder:printcolumn:name="NetBox ID",type=integer,JSONPath=`.status.id`
82+
//+kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].status`
83+
//+kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
84+
//+kubebuilder:resource:shortName=vl
85+
86+
// Vlan is the Schema for the vlans API
87+
type Vlan struct {
88+
metav1.TypeMeta `json:",inline"`
89+
metav1.ObjectMeta `json:"metadata,omitempty"`
90+
91+
Spec VlanSpec `json:"spec,omitempty"`
92+
Status VlanStatus `json:"status,omitempty"`
93+
}
94+
95+
func (v *Vlan) Conditions() *[]metav1.Condition {
96+
return &v.Status.Conditions
97+
}
98+
99+
//+kubebuilder:object:root=true
100+
101+
// VlanList contains a list of Vlan
102+
type VlanList struct {
103+
metav1.TypeMeta `json:",inline"`
104+
metav1.ListMeta `json:"metadata,omitempty"`
105+
Items []Vlan `json:"items"`
106+
}
107+
108+
func init() {
109+
SchemeBuilder.Register(&Vlan{}, &VlanList{})
110+
}
111+
112+
var ConditionVlanReadyTrue = metav1.Condition{
113+
Type: "Ready",
114+
Status: "True",
115+
Reason: "VlanSynchronized",
116+
Message: "VLAN was synchronized with NetBox",
117+
}
118+
119+
var ConditionVlanReadyFalse = metav1.Condition{
120+
Type: "Ready",
121+
Status: "False",
122+
Reason: "VlanSyncFailed",
123+
Message: "Failed to synchronize VLAN with NetBox",
124+
}

api/v1/vlanclaim_types.go

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
Copyright 2024 Swisscom (Schweiz) AG.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1
18+
19+
import (
20+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
)
22+
23+
// VLANClaimSpec defines the desired state of VLANClaim
24+
type VLANClaimSpec struct {
25+
// The unique VLAN ID (VID) for the NetBox VLAN. If not provided, the operator will claim an available VID.
26+
//+optional
27+
//+kubebuilder:validation:Minimum=1
28+
//+kubebuilder:validation:Maximum=4094
29+
VlanId int `json:"vlanId,omitempty"`
30+
31+
// The desired name for the VLAN in NetBox. If not provided, the operator will generate one.
32+
//+optional
33+
Name string `json:"name,omitempty"`
34+
35+
// The NetBox Site where this VLAN should exist
36+
//+kubebuilder:validation:Required
37+
Site string `json:"site"`
38+
39+
// The NetBox VLANGroup where this VLAN should be organized. Required if vlanId is not provided.
40+
//+optional
41+
VlanGroup string `json:"vlanGroup,omitempty"`
42+
43+
// Description that should be added to the resource in NetBox
44+
//+optional
45+
Description string `json:"description,omitempty"`
46+
47+
// Comment that should be added to the resource in NetBox
48+
//+optional
49+
Comments string `json:"comments,omitempty"`
50+
51+
// The NetBox Custom Fields that should be added to the resource in NetBox
52+
//+optional
53+
CustomFields map[string]string `json:"customFields,omitempty"`
54+
55+
// Defines whether the Resource should be preserved in NetBox when the
56+
// Kubernetes Resource is deleted.
57+
//+optional
58+
PreserveInNetbox bool `json:"preserveInNetbox,omitempty"`
59+
}
60+
61+
// VLANClaimStatus defines the observed state of VLANClaim
62+
type VLANClaimStatus struct {
63+
// The assigned VLAN ID (VID)
64+
//+optional
65+
VlanId int `json:"vlanId,omitempty"`
66+
67+
// The name of the Vlan CR created by the VLANClaim Controller
68+
//+optional
69+
VlanName string `json:"vlanName,omitempty"`
70+
71+
// Conditions represent the latest available observations of an object's state
72+
//+optional
73+
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
74+
}
75+
76+
//+kubebuilder:object:root=true
77+
//+kubebuilder:subresource:status
78+
//+kubebuilder:storageversion
79+
//+kubebuilder:printcolumn:name="VID",type=integer,JSONPath=`.status.vlanId`
80+
//+kubebuilder:printcolumn:name="Vlan Name",type=string,JSONPath=`.status.vlanName`
81+
//+kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].status`
82+
//+kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
83+
//+kubebuilder:resource:shortName=vlc
84+
85+
// VLANClaim is the Schema for the vlanclaims API
86+
type VLANClaim struct {
87+
metav1.TypeMeta `json:",inline"`
88+
metav1.ObjectMeta `json:"metadata,omitempty"`
89+
90+
Spec VLANClaimSpec `json:"spec,omitempty"`
91+
Status VLANClaimStatus `json:"status,omitempty"`
92+
}
93+
94+
func (v *VLANClaim) Conditions() *[]metav1.Condition {
95+
return &v.Status.Conditions
96+
}
97+
98+
//+kubebuilder:object:root=true
99+
100+
// VLANClaimList contains a list of VLANClaim
101+
type VLANClaimList struct {
102+
metav1.TypeMeta `json:",inline"`
103+
metav1.ListMeta `json:"metadata,omitempty"`
104+
Items []VLANClaim `json:"items"`
105+
}
106+
107+
func init() {
108+
SchemeBuilder.Register(&VLANClaim{}, &VLANClaimList{})
109+
}
110+
111+
var ConditionVlanClaimReadyTrue = metav1.Condition{
112+
Type: "Ready",
113+
Status: "True",
114+
Reason: "VlanResourceReady",
115+
Message: "VLAN Resource is ready",
116+
}
117+
118+
var ConditionVlanClaimReadyFalse = metav1.Condition{
119+
Type: "Ready",
120+
Status: "False",
121+
Reason: "VlanResourceNotReady",
122+
Message: "VLAN Resource is not ready",
123+
}
124+
125+
var ConditionVlanAssignedTrue = metav1.Condition{
126+
Type: "VlanAssigned",
127+
Status: "True",
128+
Reason: "VlanCRCreated",
129+
Message: "VLAN VID assigned and Vlan CR created",
130+
}
131+
132+
var ConditionVlanAssignedFalse = metav1.Condition{
133+
Type: "VlanAssigned",
134+
Status: "False",
135+
Reason: "VlanCRNotCreated",
136+
Message: "Failed to assign VID or create Vlan CR",
137+
}

0 commit comments

Comments
 (0)