Skip to content

Commit

Permalink
Add functionality to parse multiple prefixes (#35)
Browse files Browse the repository at this point in the history
This change introduces a new function `multiprefixloop` as a convenience
function for splitting multiple cidr prefixes govorned by the number of
bits and required offset inside each prefix.

This function might be used in instances such as dividing additional VPC
cidrs into subnets without requiring multiple instances of the funtion
to be declared in a given composition.

Additionally this contributes towards issue #2 by introducing happy path
unit tests for each function.
  • Loading branch information
mproffitt authored Aug 23, 2024
1 parent fe95f53 commit 0800924
Show file tree
Hide file tree
Showing 14 changed files with 887 additions and 126 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
render:
@for file in examples/xr-*.yaml; do \
echo ""; \
echo "Rendering $$file..."; \
crossplane beta render \
"$$file" \
apis/composition.yaml \
examples/functions.yaml; \
done

debug:
go run . --insecure --debug
101 changes: 71 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,98 +5,119 @@ A [Crossplane](https://www.crossplane.io/)
for calculating Classless Inter-Domain Routing
([CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing))
numbers.

A CIDR is an IP address allocation method that is used to improve
data routing efficiency on the internet.

## Overview

This composition function offers 4 HashiCorp compatible
IP Network Functions plus one custom wrapper. Follow the
function links for detailed explanations of the function
semantics.
This composition function offers 4 HashiCorp compatible IP Network Functions
plus two custom wrappers. Follow the function links for detailed explanations of
the function semantics.

- [cidrhost](https://developer.hashicorp.com/terraform/language/functions/cidrhost)
- [cidrnetmask](https://developer.hashicorp.com/terraform/language/functions/cidrnetmask)
- [cidrsubnet](https://developer.hashicorp.com/terraform/language/functions/cidrsubnet)
- [cidrsubnets](https://developer.hashicorp.com/terraform/language/functions/cidrsubnets)
- cidrsubnetloop wraps [cidrsubnet](https://developer.hashicorp.com/terraform/language/functions/cidrsubnet)
- multiprefixloop wraps [cidrsubnets](https://developer.hashicorp.com/terraform/language/functions/cidrsubnets)

To use this function, apply the following
[functions.yaml](examples/functions.yaml)
to your Crossplane management cluster.
```

```bash
cat <<EOF|kubectl apply -f -
apiVersion: pkg.crossplane.io/v1beta1
kind: Function
metadata:
name: upbound-function-cidr
spec:
package: xpkg.upbound.io/upbound/function-cidr:v0.1.0
package: xpkg.upbound.io/upbound/function-cidr:v0.4.0
EOF
```
Call the function from a Crossplane composition as described below.
## Terminology
The `cidrfunc` IP Network Functions have various input parameters.
Below are brief descriptions for context.
- `prefix` must be given in CIDR notation, as defined in [RFC 4632 section 3.1.](https://datatracker.ietf.org/doc/html/rfc4632#section-3.1)
- `hostnum` is a whole number that can be represented as a binary integer with no more than the number of digits remaining in the address after the given prefix.
- `newbits` is the number of additional bits with which to extend the prefix. For example, if given a prefix ending in /16 and a newbits value of 4, the resulting subnet address will have length /20.
- `netnum` is a whole number that can be represented as a binary integer with no more than newbits binary digits, which will be used to populate the additional bits added to the prefix.
- `hostnum` is a whole number that can be represented as a binary integer with
no more than the number of digits remaining in the address after the given
prefix.
- `newbits` is the number of additional bits with which to extend the prefix.
For example, if given a prefix ending in /16 and a newbits value of 4, the
resulting subnet address will have length /20.
- `netnum` is a whole number that can be represented as a binary integer with no
more than newbits binary digits, which will be used to populate the additional
bits added to the prefix.
## Usage
Specify the `cidrfunc` calculation type in the composition function input.
Valid values are as follows:
```
```yaml
- cidrhost
- cidrnetmask
- cidrsubnet
- cidrsubnets
- cidrsubnetloop
- multiprefixloop
```
Specify a custom `outputfield` in the function input parameters
when the output should appear at a different path
than the respective `status.atFunction.cidr` sub field default path.
Specify a custom `outputfield` in the function input parameters when the output
should appear at a different path than the respective `status.atFunction.cidr`
sub field default path.
All `cidrfunc` IP Network Functions require a CIDR `prefix` as input.
Provide the `prefix` directly in the
function input or specify a `prefixfield` in the XR where
the function shall pick up the `prefix` value.
Function input field names ending in `field` indicate that
the function shall read the field path value from the specified
field path in the XR.
Provide the `prefix` directly in the function input or specify a `prefixfield`
in the XR where the function shall pick up the `prefix` value.
Function input field names ending in `field` indicate that the function shall
read the field path value from the specified field path in the XR.
### cidrhost
The `cidrhost cidrfunc` requires a `hostnum` or `hostnumfield` as
function input. `hostnum` is an integer.
### cidrnetmask
The `cidrnetmask cidrfunc` does not require additional parameters
beyond the `prefix`. The `prefix` can be read from an XR field
when the `prefixField` path is specified in the function input
instead of a `prefix` value.
The `cidrnetmask cidrfunc` does not require additional parameters beyond the
`prefix`. The `prefix` can be read from an XR field when the `prefixField` path
is specified in the function input instead of a `prefix` value.
### cidrsubnet
The `cidrhost cidrsubnet` reauires a `netnum` or `netnumfield`,
and a `newbits` or `newbitsfield` as function input.
The `cidrhost cidrsubnet` requires a `netnum` or `netnumfield`, and a `newbits`
or `newbitsfield` as function input.
`netNum` is an integer.
`newBits` is one integer in an array of integers.
### cidrsubnets
The `cidrhost cidrsubnets` reauires a `newBits`
or `newBitsField` as function input.
The `cidrhost cidrsubnets` requires a `newBits` or `newBitsField` as function
input.
`newBits` is an array of integers.
### cidrsubnetloop
The `cidrhost cidrsubnetloop` reauires the following input fields.
- `newBits` (integer array) or `newBitsField`
- `netNumCount` (integer) or `netNumCountField`
- `netNumItems` (string array) or `netNumItemsField`
- `offset` or `offsetfield`
** netNumCount and netNumItems are mutually exclusive **
**`netNumCount` and `netNumItems` are mutually exclusive**
The `cidrsubnetloop` wrapper calculates `cidrsubnet` CIDRs using
the `prefix` and `newBits` parameters as input. It performs the
Expand All @@ -105,7 +126,27 @@ iteration from `iteration`+`offset`. The iterations are either from
0 to `netNumCount` -1 or from 0 to number of items in `netNumItemsCount`
or their respective values from their XR field references.
### multiprefixloop
This is an additional convenience function that takes a list of objects, each
describing a cidr prefix to split and returns the result as a
`map[string][]string` key'd on the prefix for that block.
It is most useful for scenarios where your composition requires multiple cidr
prefixes, such as splitting VPC additional CIDRs for subnet creation.
The `multiprefixloop` function requires a list of inputs with each input
containing:
- `prefix` The CIDR prefix to create subnets for
- `newBits` An integer array defining how to split the prefix
- `offset` An optional bit size to start the subnet range after
If `offset` is specified, this is prepended to the `newBits` field immediately
before calculations and then removed after the calculation is completed.
## Testing The Function
Clone the repo. Run `make debug` and in a second terminal run `make render`
and examine the output. Corresponding compositions and XR yaml can be
found in the `examples` folder.
and examine the output. Corresponding compositions and XR yaml can be found in
the `examples` folder.
4 changes: 2 additions & 2 deletions apis/composition.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ spec:
input:
apiVersion: cidr.fn.crossplane.io/v1beta1
kind: Parameters
cidrFunc: spec.parameters.cidrFunc
cidrFuncField: spec.parameters.cidrFunc
prefixField: spec.parameters.cidrBlock
newBitsField: spec.parameters.newBits
netNumItemsField: spec.parameters.azs
hostNumField: spec.parameters.hostNum
offsetField: spec.parameters.offset
outputField: spec.parameters.output
multiPrefixField: spec.parameters.subnets
12 changes: 12 additions & 0 deletions apis/definition.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ spec:
- cidrhost
- cidrnetmask
- cidrsubnetloop
- multiprefixloop
subnets:
type: array
items:
type: object
properties:
prefix:
type: string
newBits:
type: array
items:
type: integer
cidrBlock:
type: string
newBits:
Expand Down
1 change: 0 additions & 1 deletion examples/xr-cidrhost.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ spec:
cidrFunc: cidrhost
cidrBlock: 10.0.0.0/20
hostNum: 111
output: status.atFunction.cidr.hostAddress
1 change: 0 additions & 1 deletion examples/xr-cidrnetmask.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@ spec:
parameters:
cidrFunc: cidrnetmask
cidrBlock: 172.16.0.0/12
output: status.atFunction.cidr.netmask
1 change: 0 additions & 1 deletion examples/xr-cidrsubnet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@ spec:
newBits:
- 8
netNum: 3
output: status.atFunction.cidr.subnet-a
20 changes: 20 additions & 0 deletions examples/xr-multicidrsubnetsloop.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: platform.upbound.io/v1alpha1
kind: XCIDR
metadata:
name: cidr-multiprefixloop
spec:
parameters:
cidrFunc: multiprefixloop
subnets:
- prefix: 10.0.0.0/20
newBits:
- 8
- 4
- 2
- prefix: 127.0.0.0/20
newBits: [
4, 4, 4,
4, 4, 4,
5, 5, 5,
5, 5, 5,
]
Loading

0 comments on commit 0800924

Please sign in to comment.