diff --git a/Makefile b/Makefile index f045650..c0d8f95 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # Image URL to use all building/pushing image targets -IMG ?= gcr.io/aamoyel/kubipam:v0.1.2 +IMG ?= gcr.io/aamoyel/kubipam:v0.1.3 # ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. ENVTEST_K8S_VERSION = 1.29.0 diff --git a/api/v1alpha1/ipclaim_webhook.go b/api/v1alpha1/ipclaim_webhook.go index b7a493d..1820a5a 100644 --- a/api/v1alpha1/ipclaim_webhook.go +++ b/api/v1alpha1/ipclaim_webhook.go @@ -88,6 +88,13 @@ func (r *IPClaim) validateClaim() error { func (r *IPClaim) validateSpec() *field.Error { // The field helpers from the kubernetes API machinery help us return nicely // structured validation errors. + + if r.Spec.IPCidrRef != nil { + if r.Spec.IPCidrRef.Name == "" { + return field.Forbidden(field.NewPath("spec").Child("ipCidrRef").Child("name"), "'ipCidrRef.name' must be set when using 'ipCidrRef'") + } + } + if r.Spec.Type == "IP" { noRefmsg := field.Forbidden( field.NewPath("spec").Child("ipCidrRef").Child("name"), @@ -96,9 +103,6 @@ func (r *IPClaim) validateSpec() *field.Error { if r.Spec.IPCidrRef == nil { return noRefmsg } - if r.Spec.IPCidrRef.Name == "" { - return noRefmsg - } } if r.Spec.Type == "CIDR" { @@ -110,9 +114,6 @@ func (r *IPClaim) validateSpec() *field.Error { if r.Spec.IPCidrRef == nil { return noRefmsg } - if r.Spec.IPCidrRef.Name == "" { - return noRefmsg - } } if r.Spec.SpecificChildCidr == "" && r.Spec.CidrPrefixLength == 0 { diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index ad23702..53283b7 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -141,4 +141,4 @@ kind: Kustomization images: - name: aamoyel/kubipam newName: gcr.io/aamoyel/kubipam - newTag: v0.1.2 + newTag: v0.1.3 diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 8dd4565..1b79bb3 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -645,7 +645,7 @@ spec: - --metrics-bind-address=0.0.0.0:8080 command: - /manager - image: gcr.io/aamoyel/kubipam:v0.1.2 + image: gcr.io/aamoyel/kubipam:v0.1.3 livenessProbe: httpGet: path: /healthz diff --git a/examples/claim/ipclaim7.yaml b/examples/claim/ipclaim7.yaml new file mode 100644 index 0000000..c98bbd0 --- /dev/null +++ b/examples/claim/ipclaim7.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: ipam.didactiklabs.io/v1alpha1 +kind: IPClaim +metadata: + name: test7 +spec: + type: CIDR + cidrPrefixLength: 108 diff --git a/examples/claim/ipclaim8.yaml b/examples/claim/ipclaim8.yaml new file mode 100644 index 0000000..35ae62e --- /dev/null +++ b/examples/claim/ipclaim8.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: ipam.didactiklabs.io/v1alpha1 +kind: IPClaim +metadata: + name: test8 +spec: + type: CIDR + ipCidrRef: + name: test-v6 + cidrPrefixLength: 108 diff --git a/internal/controllers/ipcidr_controller.go b/internal/controllers/ipcidr_controller.go index 17e4413..73db370 100644 --- a/internal/controllers/ipcidr_controller.go +++ b/internal/controllers/ipcidr_controller.go @@ -221,10 +221,7 @@ func IPCidrProgressing(o *ipamv1alpha1.IPCidr) { }) } -func (r *IPCidrReconciler) patchIPCidrStatus( - ctx context.Context, - ipCidr *ipamv1alpha1.IPCidr, -) error { +func (r *IPCidrReconciler) patchIPCidrStatus(ctx context.Context, ipCidr *ipamv1alpha1.IPCidr) error { key := client.ObjectKeyFromObject(ipCidr) latest := &ipamv1alpha1.IPCidr{} if err := r.Client.Get(ctx, key, latest); err != nil { @@ -337,10 +334,7 @@ func (r *IPCidrReconciler) isCidrOverlapping(ctx context.Context, cr *ipamv1alph } // ipCidrReconcileRequests returns a list of reconcile.Request based on the ipcidr resource. -func ipCidrReconcileRequests( - ctx context.Context, - mgr manager.Manager, -) ([]reconcile.Request, error) { +func ipCidrReconcileRequests(ctx context.Context, mgr manager.Manager) ([]reconcile.Request, error) { IPCidrList := &ipamv1alpha1.IPCidrList{} err := mgr.GetClient().List(ctx, IPCidrList) if err != nil { diff --git a/internal/controllers/ipclaim_controller.go b/internal/controllers/ipclaim_controller.go index 30d3ece..26d56e5 100644 --- a/internal/controllers/ipclaim_controller.go +++ b/internal/controllers/ipclaim_controller.go @@ -215,10 +215,7 @@ func IPClaimProgressing(o *ipamv1alpha1.IPClaim) { }) } -func (r *IPClaimReconciler) patchIPClaimStatus( - ctx context.Context, - ipClaim *ipamv1alpha1.IPClaim, -) error { +func (r *IPClaimReconciler) patchIPClaimStatus(ctx context.Context, ipClaim *ipamv1alpha1.IPClaim) error { key := client.ObjectKeyFromObject(ipClaim) latest := &ipamv1alpha1.IPClaim{} if err := r.Client.Get(ctx, key, latest); err != nil { @@ -279,11 +276,7 @@ func (r *IPClaimReconciler) reconcileIPClaim(ctx context.Context, cr *ipamv1alph return nil } -func (r *IPClaimReconciler) getIpAddr( - ctx context.Context, - cr *ipamv1alpha1.IPClaim, - parentCidr string, -) error { +func (r *IPClaimReconciler) getIpAddr(ctx context.Context, cr *ipamv1alpha1.IPClaim, parentCidr string) error { claim, err := r.Ipamer.AcquireSpecificIP(ctx, parentCidr, cr.Spec.SpecificIPAddress) if claim == nil { err = fmt.Errorf("%w", err) @@ -307,10 +300,7 @@ func (r *IPClaimReconciler) getIpAddr( return nil } -func (r *IPClaimReconciler) getChildCidr( - ctx context.Context, - cr *ipamv1alpha1.IPClaim, -) (err error) { +func (r *IPClaimReconciler) getChildCidr(ctx context.Context, cr *ipamv1alpha1.IPClaim) (err error) { var ( claim *goipam.Prefix cidrCr *ipamv1alpha1.IPCidr @@ -348,15 +338,15 @@ func (r *IPClaimReconciler) getChildCidr( } return err } - } else if cr.Spec.SpecificChildCidr == "" { + } else { // Check if we need to use a specific parent CIDR - if cr.Spec.IPCidrRef.Name != "" { + if cr.Spec.IPCidrRef != nil { // Get parent cidr - cidrCR, err := r.getParentCidr(ctx, cr) + cidrCr, err = r.getParentCidr(ctx, cr) if err != nil { return err } - if !cidrCR.Status.Registered { + if !cidrCr.Status.Registered { err := fmt.Errorf("the cidr resource in the IPCidrRefSpec for the %s claim is not in a ready state", cr.Name) setIPClaimErrorStatus(cr, err) if patchStatusErr := r.patchIPClaimStatus(ctx, cr); patchStatusErr != nil { @@ -366,6 +356,17 @@ func (r *IPClaimReconciler) getChildCidr( } return nil } + claim, err = r.Ipamer.AcquireChildPrefix(ctx, cidrCr.Spec.Cidr, cr.Spec.CidrPrefixLength) + if err != nil { + err = fmt.Errorf("Unable to get a child cidr for your prefix lengh in the '"+cr.Spec.IPCidrRef.Name+"' , err: %w", err) + setIPClaimErrorStatus(cr, err) + if patchStatusErr := r.patchIPClaimStatus(ctx, cr); patchStatusErr != nil { + err = kerror.NewAggregate([]error{err, patchStatusErr}) + err = fmt.Errorf("unable to patch status after reconciliation failed: %w", err) + return err + } + return err + } } else { // find available parent cidr for this prefix length cidrList := &ipamv1alpha1.IPCidrList{} @@ -425,10 +426,7 @@ func setIPClaimErrorStatus(cr *ipamv1alpha1.IPClaim, err error) { } // ipClaimReconcileRequests returns a list of reconcile.Request based on the ipclaim resource. -func ipClaimReconcileRequests( - ctx context.Context, - mgr manager.Manager, -) ([]reconcile.Request, error) { +func ipClaimReconcileRequests(ctx context.Context, mgr manager.Manager) ([]reconcile.Request, error) { IPClaimList := &ipamv1alpha1.IPClaimList{} err := mgr.GetClient().List(ctx, IPClaimList) if err != nil { @@ -446,10 +444,7 @@ func ipClaimReconcileRequests( return requests, nil } -func (r *IPClaimReconciler) getParentCidr( - ctx context.Context, - cr *ipamv1alpha1.IPClaim, -) (*ipamv1alpha1.IPCidr, error) { +func (r *IPClaimReconciler) getParentCidr(ctx context.Context, cr *ipamv1alpha1.IPClaim) (*ipamv1alpha1.IPCidr, error) { cidrCR := &ipamv1alpha1.IPCidr{} cidrNamepacedName := types.NamespacedName{ Name: cr.Spec.IPCidrRef.Name, @@ -514,11 +509,7 @@ func (r *IPClaimReconciler) initRegisteredClaims(ctx context.Context) error { } // checkParentCidr return an error when the parent cidr is not registered in the ipam. -func (r *IPClaimReconciler) checkParentCidr( - ctx context.Context, - claimCr *ipamv1alpha1.IPClaim, - parentCidr string, -) error { +func (r *IPClaimReconciler) checkParentCidr(ctx context.Context, claimCr *ipamv1alpha1.IPClaim, parentCidr string) error { _, err := r.Ipamer.PrefixFrom(ctx, parentCidr) if err != nil { err = fmt.Errorf("unable to find parent cidr in the ipam, err: %w", err)