Skip to content

Commit

Permalink
This commit makes it possible to:
Browse files Browse the repository at this point in the history
- Deploy IPAM with clusterctl
- Reconsile CAPI's ipaddressclaims with this managers ippools

Signed-off-by: peppi-lotta <[email protected]>
  • Loading branch information
peppi-lotta committed Oct 24, 2024
1 parent 81f0c6d commit 5fa145b
Show file tree
Hide file tree
Showing 16 changed files with 2,404 additions and 420 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ ARG BUILD_IMAGE=docker.io/golang:1.22.8@sha256:b274ff14d8eb9309b61b1a45333bf0559
ARG BASE_IMAGE=gcr.io/distroless/static:nonroot@sha256:9ecc53c269509f63c69a266168e4a687c7eb8c0cfd753bd8bfcaa4f58a90876f

# Build the manager binary on golang image
FROM $BUILD_IMAGE as builder
FROM $BUILD_IMAGE AS builder
WORKDIR /workspace

# Run this with docker build --build_arg $(go env GOPROXY) to override the goproxy
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Deploys IPAM CRDs and deploys IPAM controllers
Runs IPAM controller locally

```sh
kubectl scale -n capm3-system \
kubectl scale -n ipam-system \
deployment.v1.apps/metal3-ipam-controller-manager --replicas 0
make run
```
Expand Down
7 changes: 3 additions & 4 deletions config/default/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

# Adds namespace to all resources. Keep it in capm3-system, as it is a
# dependency for CAPM3
namespace: capm3-system
# Adds namespace to all resources.
namespace: ipam-system

namePrefix: ipam-

labels:
- includeSelectors: true
pairs:
cluster.x-k8s.io/provider: infrastructure-metal3
cluster.x-k8s.io/provider: ipam-metal3

resources:
- ../rbac
Expand Down
7 changes: 7 additions & 0 deletions config/manager/manager.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
apiVersion: v1
kind: Namespace
metadata:
labels:
control-plane: controller-manager
name: system
---
apiVersion: apps/v1
kind: Deployment
metadata:
Expand Down
40 changes: 40 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,46 @@ rules:
- clusters/status
verbs:
- get
- apiGroups:
- ipam.cluster.x-k8s.io
resources:
- ipaddressclaims
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- ipam.cluster.x-k8s.io
resources:
- ipaddressclaims/status
verbs:
- get
- patch
- update
- apiGroups:
- ipam.cluster.x-k8s.io
resources:
- ipaddresses
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- ipam.cluster.x-k8s.io
resources:
- ipaddresses/status
verbs:
- get
- patch
- update
- apiGroups:
- ipam.metal3.io
resources:
Expand Down
39 changes: 37 additions & 2 deletions controllers/ippool_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
capipamv1 "sigs.k8s.io/cluster-api/exp/ipam/api/v1beta1"
"sigs.k8s.io/cluster-api/util/annotations"
"sigs.k8s.io/cluster-api/util/patch"
"sigs.k8s.io/cluster-api/util/predicates"
Expand Down Expand Up @@ -55,6 +56,10 @@ type IPPoolReconciler struct {
// +kubebuilder:rbac:groups=ipam.metal3.io,resources=ipclaims/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=ipam.metal3.io,resources=ipaddresses,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=ipam.metal3.io,resources=ipaddresses/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=ipam.cluster.x-k8s.io,resources=ipaddressclaims,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=ipam.cluster.x-k8s.io,resources=ipaddressclaims/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=ipam.cluster.x-k8s.io,resources=ipaddresses,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=ipam.cluster.x-k8s.io,resources=ipaddresses/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=clusters,verbs=get;list;watch
// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=clusters/status,verbs=get
// +kubebuilder:rbac:groups="",resources=events,verbs=get;list;watch;create;update;patch
Expand Down Expand Up @@ -97,7 +102,7 @@ func (r *IPPoolReconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ c
ipamv1IPPool.ObjectMeta.Labels = make(map[string]string)
}
ipamv1IPPool.ObjectMeta.Labels[clusterv1.ClusterNameLabel] = *ipamv1IPPool.Spec.ClusterName
ipamv1IPPool.ObjectMeta.Labels[clusterv1.ProviderNameLabel] = "infrastructure-metal3"
ipamv1IPPool.ObjectMeta.Labels[clusterv1.ProviderNameLabel] = "ipam-metal3"

// Fetch the Cluster. Ignore an error if the deletion timestamp is set
err = r.Client.Get(ctx, key, cluster)
Expand Down Expand Up @@ -171,7 +176,7 @@ func (r *IPPoolReconciler) reconcileDelete(ctx context.Context,
}

// SetupWithManager will add watches for this controller.
func (r *IPPoolReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
func (r *IPPoolReconciler) SetupWithManagerForIPClaim(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
return ctrl.NewControllerManagedBy(mgr).
For(&ipamv1.IPPool{}).
WithOptions(options).
Expand All @@ -183,6 +188,19 @@ func (r *IPPoolReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manage
Complete(r)
}

// SetupWithManager will add watches for this controller.
func (r *IPPoolReconciler) SetupWithManagerForIPAddressClaim(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
return ctrl.NewControllerManagedBy(mgr).
For(&ipamv1.IPPool{}).
WithOptions(options).
Watches(
&capipamv1.IPAddressClaim{},
handler.EnqueueRequestsFromMapFunc(r.IPAddressClaimToIPPool),
).
WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(ctrl.LoggerFrom(ctx), r.WatchFilterValue)).
Complete(r)
}

// IPClaimToIPPool will return a reconcile request for a
// Metal3DataTemplate if the event is for a
// IPClaim and that IPClaim references a Metal3DataTemplate.
Expand All @@ -206,6 +224,23 @@ func (r *IPPoolReconciler) IPClaimToIPPool(_ context.Context, obj client.Object)
return []ctrl.Request{}
}

func (r *IPPoolReconciler) IPAddressClaimToIPPool(_ context.Context, obj client.Object) []ctrl.Request {
if ipac, ok := obj.(*capipamv1.IPAddressClaim); ok {
if ipac.Spec.PoolRef.Name != "" {
namespace := ipac.Namespace
return []ctrl.Request{
{
NamespacedName: types.NamespacedName{
Name: ipac.Spec.PoolRef.Name,
Namespace: namespace,
},
},
}
}
}
return []ctrl.Request{}
}

func checkRequeueError(err error, errMessage string) (ctrl.Result, error) {
if err == nil {
return ctrl.Result{}, nil
Expand Down
60 changes: 60 additions & 0 deletions controllers/ippool_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/ptr"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
capipamv1 "sigs.k8s.io/cluster-api/exp/ipam/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
Expand Down Expand Up @@ -407,4 +408,63 @@ var _ = Describe("IPPool controller", func() {
},
),
)

type TestCaseK8SIPACToM3IPP struct {
IPAddressClaim *capipamv1.IPAddressClaim
ExpectRequest bool
}

DescribeTable("IPAddressClaim To IPPool tests",
func(tc TestCaseK8SIPACToM3IPP) {
r := IPPoolReconciler{}
obj := client.Object(tc.IPAddressClaim)
reqs := r.IPAddressClaimToIPPool(context.Background(), obj)

if tc.ExpectRequest {
Expect(len(reqs)).To(Equal(1), "Expected 1 request, found %d", len(reqs))

req := reqs[0]
Expect(req.NamespacedName.Name).To(Equal(tc.IPAddressClaim.Spec.PoolRef.Name),
"Expected name %s, found %s", tc.IPAddressClaim.Spec.PoolRef.Name, req.NamespacedName.Name)
} else {
Expect(len(reqs)).To(Equal(0), "Expected 0 request, found %d", len(reqs))

}
},
Entry("No IPPool in Spec",
TestCaseK8SIPACToM3IPP{
IPAddressClaim: &capipamv1.IPAddressClaim{
ObjectMeta: testObjectMeta,
Spec: capipamv1.IPAddressClaimSpec{},
},
ExpectRequest: false,
},
),
Entry("IPPool in Spec, with namespace",
TestCaseK8SIPACToM3IPP{
IPAddressClaim: &capipamv1.IPAddressClaim{
ObjectMeta: testObjectMeta,
Spec: capipamv1.IPAddressClaimSpec{
PoolRef: corev1.TypedLocalObjectReference{
Name: "abc",
},
},
},
ExpectRequest: true,
},
),
Entry("IPPool in Spec, no namespace",
TestCaseK8SIPACToM3IPP{
IPAddressClaim: &capipamv1.IPAddressClaim{
ObjectMeta: testObjectMeta,
Spec: capipamv1.IPAddressClaimSpec{
PoolRef: corev1.TypedLocalObjectReference{
Name: "abc",
},
},
},
ExpectRequest: true,
},
),
)
})
9 changes: 9 additions & 0 deletions controllers/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
ipamv1 "github.com/metal3-io/ip-address-manager/api/v1alpha1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
capipamv1 "sigs.k8s.io/cluster-api/exp/ipam/api/v1beta1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"
Expand All @@ -57,6 +58,7 @@ func init() {
_ = apiextensionsv1.AddToScheme(scheme.Scheme)
_ = clusterv1.AddToScheme(scheme.Scheme)
_ = ipamv1.AddToScheme(scheme.Scheme)
_ = capipamv1.AddToScheme(scheme.Scheme)
}

func setupScheme() *runtime.Scheme {
Expand All @@ -70,6 +72,10 @@ func setupScheme() *runtime.Scheme {
panic(err)
}

if err := capipamv1.AddToScheme(s); err != nil {
panic(err)
}

return s
}
func TestAPIs(t *testing.T) {
Expand All @@ -94,6 +100,9 @@ var _ = BeforeSuite(func() {
err = ipamv1.AddToScheme(scheme.Scheme)
Expect(err).NotTo(HaveOccurred())

err = capipamv1.AddToScheme(scheme.Scheme)
Expect(err).NotTo(HaveOccurred())

err = apiextensionsv1.AddToScheme(scheme.Scheme)
Expect(err).NotTo(HaveOccurred())

Expand Down
37 changes: 35 additions & 2 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,13 @@ as follows :
It is used to verify that the allocated address belongs to this subnet.
* **prefix**: override of the default prefix for this pool
* **gateway**: override of the default gateway for this pool
* **DNSServers**: override of the default dns servers for this pool
## IPClaim
An IPClaim is an object representing a request for an IP address allocation.
Example pool:
Example IPClaim:
```yaml
apiVersion: ipam.metal3.io/v1alpha1
Expand All @@ -78,7 +79,7 @@ The *spec* field contains the following :
An IPAddress is an object representing an IP address allocation.
Example pool:
Example IPAddress:
```yaml
apiVersion: ipam.metal3.io/v1alpha1
Expand All @@ -105,8 +106,40 @@ The *spec* field contains the following :
* **address**: the allocated IP address
* **prefix**: the prefix for this address
* **gateway**: the gateway for this address
* **DNSServers**: a list of dns servers
## Metal3 dev env examples
You can find CR examples in the
[Metal3-io dev env project](https://github.com/metal3-io/metal3-dev-env)
## Handling CAPI CRs
This IPAM can be deployed and used as an
[IPAM provider](https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/book/src/reference/glossary.md#ipam-provider)for
[CAPI](https://github.com/kubernetes-sigs/cluster-api).
IPPool reconsiles (metal3)ipclaims into (metal3)ipaddresses
and (capi)ipaddressclaims into (capi)ipaddresses.
### IPAddressClaim
Check out more on [IPAddressClaim docs](https://docs.openshift.com/container-platform/4.16/rest_api/network_apis/ipaddressclaim-ipam-cluster-x-k8s-io-v1beta1.html).
### IpAddress
Check out more on [IPAddress docs](https://docs.openshift.com/container-platform/4.16/rest_api/network_apis/ipaddress-ipam-cluster-x-k8s-io-v1beta1.html).
### Set up via clusterctl
Since it's not added to the built-in list of providers yet,
you'll need to add the following to your
```$XDG_CONFIG_HOME/cluster-api/clusterctl.yaml```
if you want to install it using ```clusterctl init --ipam metal3```:

```yaml
providers:
- name: metal3
url: https://github.com/metal3-io/ip-address-manager/releases/latest/ipam-components.yaml
type: IPAMProvider
```
2 changes: 1 addition & 1 deletion examples/generate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ OUTPUT_DIR=${OUTPUT_DIR:-${SOURCE_DIR}/_out}

# Cluster.
export CLUSTER_NAME="${CLUSTER_NAME:-test1}"
export NAMESPACE="${NAMESPACE:-capm3-system}"
export NAMESPACE="${NAMESPACE:-ipam-system}"

# Outputs.
COMPONENTS_CERT_MANAGER_GENERATED_FILE=${OUTPUT_DIR}/cert-manager.yaml
Expand Down
10 changes: 10 additions & 0 deletions examples/ippool/ippool.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,13 @@ spec:
pool:
name: pool1
namespace: ${NAMESPACE}
---
apiVersion: ipam.cluster.x-k8s.io/v1beta1
kind: IPAddressClaim
metadata:
name: ${CLUSTER_NAME}-controlplane-template-1-provisioning-pool
spec:
poolRef:
apiGroup: ipam.metal3.io
kind: IPPool
name: pool1
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: ipam-controller-manager
namespace: capm3-system
namespace: ipam-system
spec:
template:
spec:
Expand Down
Loading

0 comments on commit 5fa145b

Please sign in to comment.