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
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ NetBox Operator extends the Kubernetes API by allowing users to manage NetBox re
- kind
- docker cli

## Installation methods

There are several ways to install NetBox Operator on your Cluster:

- NetBox Operator Helm Chart. More information: <https://github.com/netbox-community/netbox-chart/>
- Manifests in <config/default> of this repo. Make sure to first set the correct image using `kustomize edit set image controller=<correctimage>`. Images can be found on the Releases page on GitHub
- The Makefile targets in this repository.
- For debugging and developing, please read further below.

# How to use NetBox Operator

## Running both NetBox Operator and NetBox on a local kind cluster
Expand Down Expand Up @@ -46,6 +55,25 @@ Example of assigning a Prefix using PrefixClaim:

Key information can be found in the yaml formatted output of these resources, as well as in the events and Operator logs.

# Mixed usage of Prefixes

Note that NetBox does handle the Address management of Prefixes separately from IP Ranges and IP Addresses. This is important to know when you plan to use the same NetBox Prefix as a parentPrefix for your IpAddressClaims, IpRangeClaims and PrefixClaims.

Example:

- Assume you use an existing empty NetBox Prefix "192.168.0.0/24" as the `.spec.parentPrefix` for your PrefixClaims, IpAddressClaims and IpRangeClaims.
- You create a PrefixClaim with `.spec.prefixLength` of `/25`, NetBox Operator will assign "192.168.0.0/25"
- You create a IpAddressClaim, NetBox Operator will assign "192.168.0.1/32". Important: NetBox ignores the Prefix in that case and will not return "192.168.0.129" as the first available IP!
- You create a IpAddressClaim with `.spec.size` of `2`, NetBox Operator will assign "192.168.0.2/32" to "192.168.0.3/32". Important: NetBox ignores the Prefix in that case and will not return "192.168.0.129" as the first available IP!


This means that you need to plan your automation carefully. As a rule of thumb:
- If you plan mixed use of the same parentPrefix for both single IPs (/32s) as well as Prefixes (non /32s), use PrefixClaims for everything and avoid using IpRangeClaims and IpAddressClaims.
- If you are in full control of a Prefix and you know it will only be used for assigning IP Addresses and IP Ranges, you can use IpAddressClaims and IpRangeClaims.
- If you don't know what the parentPrefix is used for, avoid using IpAddressClaims and IpRangeClaims.

The same applies if you use parentPrefixSelector with PrefixClaims. The above example is IPv4 based but will be the same with IPv6 equivalents.

# Restoration from NetBox

In the case that the cluster containing the NetBox Custom Resources managed by this NetBox Operator is not backed up (e.g. using Velero), we need to be able to restore some information from NetBox. This includes two mechanisms implemented in this NetBox Operator:
Expand Down Expand Up @@ -97,6 +125,18 @@ For the monitoring of the state of the CRs reconciled by the operator [kube stat

[kube state metrics]: https://github.com/kubernetes/kube-state-metrics

# FAQ

## What is the difference between `.spec.customFields` and `.spec.parentPrefixSelector`?

`.spec.customFields` are the NetBox Custom Fields assigned to the resource in NetBox.
`.spec.parentPrefixSelector` is used by a Claim Controller (e.g. the controller of PrefixClaim) to find a suitable Prefix to get e.g. a Prefix from.

## What is the difference between `.spec.tenant` and `.spec.parentPrefixSelector.tenant`?

`.spec.tenant` is the tenant that is assigned to the resource in NetBox.
`.spec.parentPrefixSelector.tenant` is used by a Claim Controller (e.g. the controller of PrefixClaim) to find a suitable Prefix to get e.g. a Prefix from.

# Contributing

We cordially invite collaboration from the community to enhance the quality and functionality of this project. Whether you are addressing bugs, introducing new features, refining documentation, or assisting with items on our to-do list, your contributions are highly valued and greatly appreciated. Please take a look at [Contribution guide] for more details.
Expand Down
42 changes: 33 additions & 9 deletions api/v1/ipaddress_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,39 +20,63 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.

// IpAddressSpec defines the desired state of IpAddress
type IpAddressSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file

// The IP Address in CIDR notation that should be reserved in NetBox
// Field is immutable, required
// Example: "192.168.0.1/32"
//+kubebuilder:validation:Format=cidr
//+kubebuilder:validation:XValidation:rule="self == oldSelf",message="Field 'ipAddress' is immutable"
//+kubebuilder:validation:Required
IpAddress string `json:"ipAddress"`

// The NetBox Tenant to be assigned to this resource in NetBox. Use the `name` value instead of the `slug` value
// Field is immutable, not required
// Example: "Initech" or "Cyberdyne Systems"
//+kubebuilder:validation:XValidation:rule="self == oldSelf",message="Field 'tenant' is immutable"
Tenant string `json:"tenant,omitempty"`

// The NetBox Custom Fields that should be added to the resource in NetBox.
// Note that currently only Text Type is supported (GitHub #129)
// More info on NetBox Custom Fields:
// https://github.com/netbox-community/netbox/blob/main/docs/customization/custom-fields.md
// Field is mutable, not required
// Example:
// customfield1: "Production"
// customfield2: "This is a string"
CustomFields map[string]string `json:"customFields,omitempty"`

// Comment that should be added to the resource in NetBox
// Field is mutable, not required
Comments string `json:"comments,omitempty"`

// Description that should be added to the resource in NetBox
// Field is mutable, not required
Description string `json:"description,omitempty"`

// Defines whether the Resource should be preserved in NetBox when the
// Kubernetes Resource is deleted.
// - When set to true, the resource will not be deleted but preserved in
// NetBox upon CR deletion
// - When set to false, the resource will be cleaned up in NetBox
// upon CR deletion
// Setting preserveInNetbox to true is mandatory if the user wants to restore
// resources from NetBox (e.g. Sticky CIDRs even if resources are deleted and
// recreated in Kubernetes)
// Field is mutable, not required
PreserveInNetbox bool `json:"preserveInNetbox,omitempty"`
}

// IpAddressStatus defines the observed state of IpAddress
type IpAddressStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
// The ID of the resource in NetBox
IpAddressId int64 `json:"id,omitempty"`

// The URL to the resource in the NetBox UI. Note that the base of this
// URL depends on the runtime config of NetBox Operator
IpAddressUrl string `json:"url,omitempty"`

// Conditions represent the latest available observations of an object's state
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
}

Expand All @@ -66,7 +90,7 @@ type IpAddressStatus struct {
//+kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
// +kubebuilder:resource:shortName=ip

// IpAddress is the Schema for the ipaddresses API
// IpAddress allows to create a NetBox IP Address. More info about NetBox IP Addresses: https://github.com/netbox-community/netbox/blob/main/docs/models/ipam/ipaddress.md
type IpAddress struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Expand Down
47 changes: 37 additions & 10 deletions api/v1/ipaddressclaim_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,42 +20,65 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.

// IpAddressClaimSpec defines the desired state of IpAddressClaim
type IpAddressClaimSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file

// The NetBox Prefix from which this IP Address should be claimed from
// Field is immutable, required
// Example: "192.168.0.0/20"
//+kubebuilder:validation:Required
//+kubebuilder:validation:Format=cidr
//+kubebuilder:validation:XValidation:rule="self == oldSelf",message="Field 'parentPrefix' is immutable"
ParentPrefix string `json:"parentPrefix"`

// The NetBox Tenant to be assigned to this resource in NetBox. Use the `name` value instead of the `slug` value
// Field is immutable, not required
// Example: "Initech" or "Cyberdyne Systems"
//+kubebuilder:validation:XValidation:rule="self == oldSelf",message="Field 'tenant' is immutable"
Tenant string `json:"tenant,omitempty"`

// The NetBox Custom Fields that should be added to the resource in NetBox.
// Note that currently only Text Type is supported (GitHub #129)
// More info on NetBox Custom Fields:
// https://github.com/netbox-community/netbox/blob/main/docs/customization/custom-fields.md
// Field is mutable, not required
// Example:
// customfield1: "Production"
// customfield2: "This is a string"
CustomFields map[string]string `json:"customFields,omitempty"`

// Comment that should be added to the resource in NetBox
// Field is mutable, not required
Comments string `json:"comments,omitempty"`

// Description that should be added to the resource in NetBox
// Field is mutable, not required
Description string `json:"description,omitempty"`

// Defines whether the Resource should be preserved in NetBox when the
// Kubernetes Resource is deleted.
// - When set to true, the resource will not be deleted but preserved in
// NetBox upon CR deletion
// - When set to false, the resource will be cleaned up in NetBox
// upon CR deletion
// Setting preserveInNetbox to true is mandatory if the user wants to restore
// resources from NetBox (e.g. Sticky CIDRs even if resources are deleted and
// recreated in Kubernetes)
// Field is mutable, not required
PreserveInNetbox bool `json:"preserveInNetbox,omitempty"`
}

// IpAddressClaimStatus defines the observed state of IpAddressClaim
type IpAddressClaimStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file

// The assigned IP Address in CIDR notation
IpAddress string `json:"ipAddress,omitempty"`

// The assigned IP Address in Dot Decimal notation
IpAddressDotDecimal string `json:"ipAddressDotDecimal,omitempty"`

// The name of the IpAddress CR created by the IpAddressClaim Controller
IpAddressName string `json:"ipAddressName,omitempty"`

// Conditions represent the latest available observations of an object's state
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
}

Expand All @@ -68,7 +91,11 @@ type IpAddressClaimStatus struct {
//+kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
// +kubebuilder:resource:shortName=ipc

// IpAddressClaim is the Schema for the ipaddressclaims API
// IpAddressClaim allows to claim a NetBox IP Address from an existing Prefix.
// The IpAddressClaim Controller will try to assign an available IP Address
// from the Prefix that is defined in the spec and if successful it will create
// the IpAddress CR. More info about NetBox IP Addresses:
// https://github.com/netbox-community/netbox/blob/main/docs/models/ipam/ipaddress.md
type IpAddressClaim struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Expand Down
42 changes: 36 additions & 6 deletions api/v1/iprange_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,41 +20,71 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.

// IpRangeSpec defines the desired state of IpRange
type IpRangeSpec struct {
// the startAddress is the first ip address included in the ip range
// The first IP in CIDR notation that should be included in the NetBox IP Range
// Field is immutable, required
// Example: "192.168.0.1/32"
//+kubebuilder:validation:Format=cidr
//+kubebuilder:validation:XValidation:rule="self == oldSelf",message="Field 'startAddress' is immutable"
//+kubebuilder:validation:Required
StartAddress string `json:"startAddress"`

// the endAddress is the last ip address included in the ip range
// The last IP in CIDR notation that should be included in the NetBox IP Range
// Field is immutable, required
// Example: "192.168.0.20/32"
//+kubebuilder:validation:Format=cidr
//+kubebuilder:validation:XValidation:rule="self == oldSelf",message="Field 'endAddress' is immutable"
//+kubebuilder:validation:Required
EndAddress string `json:"endAddress"`

// The NetBox Tenant to be assigned to this resource in NetBox. Use the `name` value instead of the `slug` value
// Field is immutable, not required
// Example: "Initech" or "Cyberdyne Systems"
//+kubebuilder:validation:XValidation:rule="self == oldSelf",message="Field 'tenant' is immutable"
Tenant string `json:"tenant,omitempty"`

// The NetBox Custom Fields that should be added to the resource in NetBox.
// Note that currently only Text Type is supported (GitHub #129)
// More info on NetBox Custom Fields:
// https://github.com/netbox-community/netbox/blob/main/docs/customization/custom-fields.md
// Field is mutable, not required
// Example:
// customfield1: "Production"
// customfield2: "This is a string"
CustomFields map[string]string `json:"customFields,omitempty"`

// Comment that should be added to the resource in NetBox
// Field is mutable, not required
Comments string `json:"comments,omitempty"`

// Description that should be added to the resource in NetBox
// Field is mutable, not required
Description string `json:"description,omitempty"`

// Defines whether the Resource should be preserved in NetBox when the
// Kubernetes Resource is deleted.
// - When set to true, the resource will not be deleted but preserved in
// NetBox upon CR deletion
// - When set to false, the resource will be cleaned up in NetBox
// upon CR deletion
// Setting preserveInNetbox to true is mandatory if the user wants to restore
// resources from NetBox (e.g. Sticky CIDRs even if resources are deleted and
// recreated in Kubernetes)
// Field is mutable, not required
PreserveInNetbox bool `json:"preserveInNetbox,omitempty"`
}

// IpRangeStatus defines the observed state of IpRange
type IpRangeStatus struct {
// The ID of the resource in NetBox
IpRangeId int64 `json:"id,omitempty"`

// The URL to the resource in the NetBox UI. Note that the base of this
// URL depends on the runtime config of NetBox Operator
IpRangeUrl string `json:"url,omitempty"`

// Conditions represent the latest available observations of an object's state
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
}

Expand All @@ -69,7 +99,7 @@ type IpRangeStatus struct {
//+kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
// +kubebuilder:resource:shortName=ipr

// IpRange is the Schema for the ipranges API
// IpRange allows to create a NetBox IP Range. More info about NetBox IP Ranges: https://github.com/netbox-community/netbox/blob/main/docs/models/ipam/iprange.md
type IpRange struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Expand Down
Loading