-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(): layer2 support for CAPP #787
base: main
Are you sure you want to change the base?
Conversation
Signed-off-by: rahulii <[email protected]>
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: rahulii The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Signed-off-by: rahulii <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
Signed-off-by: rahulii <[email protected]>
Converting to draft. This can't be merged until the controllers can meaningfully reconcile the proposed CRD changes and provision Equinix Metal devices to fit the desired spec. |
Signed-off-by: rahulii <[email protected]>
Signed-off-by: rahulii <[email protected]>
Signed-off-by: rahulii <[email protected]>
Signed-off-by: rahulii <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
few minor comments
api/v1beta1/packetmachine_types.go
Outdated
// If not specified, the first available IP address from the IP address range will be assigned. | ||
// This is useful when you want to reserve some IP addresses for other purposes for eg Gateways, DNS etc. | ||
// +optional | ||
AssignmentRange string `json:"assignmentRange,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you specify the expected format here ? Also add a validation if the format in valid.
Also can a user configure multiple address ranges as below ?
e.g. 10.60.10.2-10.60.10.9, 10.60.10.11-10.60.10.20
} | ||
|
||
func (c *Config) GetTemplate() (string, error) { | ||
tmpl, err := template.New("layer-2-user-data").Parse(configTemplate) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably mode this under NewConfig(), we need to initialize and parse the template only once.
And move the tmpl.Execute as a separate utility method.
internal/layer2/mime.go
Outdated
// GenerateInitDocument generates a multipart document with cloud-config data | ||
func GenerateInitDocument(rawUserData, layer2UserData string) (string, error) { | ||
var buf bytes.Buffer | ||
mpWriter := multipart.NewWriter(&buf) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mpWriter := multipart.NewWriter(&buf) | |
mpWriter := multipart.NewWriter(&buf) | |
defer mpWriter.Close() |
|
||
// execute the template and save the output to a buffer | ||
var output bytes.Buffer | ||
if err := tmpl.Execute(&output, c); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
support for adding route configuration to user data script
internal/layer2/mime.go
Outdated
) | ||
|
||
// GenerateInitDocument generates a multipart document with cloud-config data | ||
func GenerateInitDocument(rawUserData, layer2UserData string) (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's make this more generic, something like append input user data and multiple clould config could be added as deemed necessary
@rahuli few noted todo's Move the layer2 user data template to the default flavor PacketMachineTemplate spec found in templates/cluster-template.yaml |
Signed-off-by: rahulii <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rahulii looks fine overall, few comments on making this approach more generic.
@@ -8,5 +8,5 @@ spec: | |||
spec: | |||
containers: | |||
# Change the value of image field below to your controller image URL | |||
- image: quay.io/equinix-oss/cluster-api-provider-packet:dev | |||
- image: docker.io/rahulsawra/cluster-api-provider-packet-amd64:dev |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keep this for your local testing only
@@ -8,4 +8,4 @@ spec: | |||
spec: | |||
containers: | |||
- name: manager | |||
imagePullPolicy: IfNotPresent | |||
imagePullPolicy: Always |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
local testing only
if bootstrapStripped != "" { | ||
if err := yaml.Unmarshal([]byte(bootstrapStripped), &bootstrapConfig); err != nil { | ||
return "", fmt.Errorf("error parsing bootstrap YAML: %v", err) | ||
} | ||
} else { | ||
bootstrapConfig = make(map[string]interface{}) | ||
} | ||
|
||
if layer2Stripped != "" { | ||
if err := yaml.Unmarshal([]byte(layer2Stripped), &layer2UserDataConfig); err != nil { | ||
return "", fmt.Errorf("error parsing layer2 YAML: %v", err) | ||
} | ||
} else { | ||
layer2UserDataConfig = make(map[string]interface{}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bootstrapConfig := make(map[string]interface{})
if err := yaml.Unmarshal([]byte(layer2Stripped), &layer2UserDataConfig); err != nil {
return "", fmt.Errorf("error parsing layer2 YAML: %v", err)
}
layer2UserDataConfig := make(map[string]interface{})
if err := yaml.Unmarshal([]byte(layer2Stripped), &layer2UserDataConfig); err != nil {
return "", fmt.Errorf("error parsing layer2 YAML: %v", err)
}
|
||
for i, line := range lines { | ||
trimmedLine := strings.TrimSpace(line) | ||
switch trimmedLine { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this assumes there will not be any other header !
Can we modify this to be more generic - is there a way to identify headers apart from string equals
} | ||
|
||
// MergeConfigs combines bootstrap data with layer2 config | ||
func (m *CloudConfigMerger) MergeConfigs(bootstrapData string, layer2UserData string) (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we make this generic as well ?
CloudConfigMerger.WithBootstrapData(bdata).
WithLayer2Data(l2data).
WithAddlUserDatas([]userdatas). // this can be optional and can be extensible
MergeConfigs()
Signed-off-by: rahulii <[email protected]>
Signed-off-by: rahulii <[email protected]>
Signed-off-by: rahulii <[email protected]>
Signed-off-by: rahulii <[email protected]>
Signed-off-by: rahulii <[email protected]>
Signed-off-by: rahulii <[email protected]>
ipam support
|
Signed-off-by: rahulii <[email protected]>
// assignVXLAN assigns a VXLAN to a port | ||
func (r *PacketMachineReconciler) assignVXLAN(ctx context.Context, portID, vxlanStr string) error { | ||
_, resp, err := r.PacketClient.PortsApi.AssignPort(ctx, portID).PortAssignInput(metal.PortAssignInput{ | ||
Vnid: &vxlanStr, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's check if this is anyway to fetch vxlan id from vlan value - for ease of configuration / usability
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are examples here: https://github.com/equinix/terraform-provider-equinix/blob/343c8fc6a8d3674f3067629e146855c1d3d96dbe/internal/resources/metal/port/helpers.go#L145
Either vlan_ids
or vxlan_ids
are accepted in the Terraform equinix_metal_port
resource. The batch port assignment API accepts either format.
https://deploy.equinix.com/developers/api/metal/#tag/Ports/operation/createPortVlanAssignmentBatch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Vnid
in the PortAssignInput will also take either format: https://deploy.equinix.com/developers/api/metal/#tag/Ports/operation/assignPort
In Terraform, we had to be careful in some usage so that Terraform wouldn't get into a drift-detected state in places where an Equinix Metal API VLAN ID (UUID) could be returned in response despite a VXLAN ID (1234) value being supplied in the request.
Signed-off-by: rahulii <[email protected]>
Signed-off-by: rahulii <[email protected]>
Signed-off-by: rahulii <[email protected]>
added ipaddress claim deletion
Signed-off-by: rahulii <[email protected]>
Signed-off-by: rahulii <[email protected]>
Signed-off-by: rahulii <[email protected]>
Signed-off-by: rahulii <[email protected]>
Signed-off-by: rahulii <[email protected]>
✨ API and CRD changes for L2 support
This draft PR implements the API changes for design described in design doc (L2 design). This branch is being used to work through the design, build intuition, and gain early insights and feedback.
What this PR does / why we need it:
Which issue(s) this PR fixes (optional, in
fixes #<issue number>(, fixes #<issue_number>, ...)
format, will close the issue(s) when PR gets merged):Part of #613