Skip to content

Conversation

@aldokimi
Copy link

@aldokimi aldokimi commented Nov 22, 2025

Summary

Adds complete Trunk resource controller implementation with subport implementation (which is necessary for the Trunk type), dependency handling, and comprehensive test coverage.

Key Features

  • Full CRUD operations for OpenStack trunks
  • Subport reconciliation (add/remove/update)
  • Dependency management (ports, projects)
  • Resource adoption and import support
  • Comprehensive test coverage

Testing

  • Unit tests for all actuator methods
  • Test coverage 35.7%
  • All tests passing

E2E Testing

-All resources are created in the K8s side
-All resources are created in the Openstack side
-All CRUD functionalities are passing the tests

Checklist

  • Code follows project style guidelines
  • Tests added/updated and passing
  • Documentation updated
  • Generated files included
  • No breaking changes

@github-actions github-actions bot added the semver:major Breaking change label Nov 22, 2025
@aldokimi
Copy link
Author

This fixes #364 which is mentioned as well in #577

Copy link
Contributor

@winiciusallan winiciusallan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, @aldokimi! I've left a few comments in the API types. Thanks for submitting this pull request, it will be very important in achieving parity with CAPO.

type Subport struct {
// portRef is a reference to the ORC Port which will be used as a subport.
// +required
PortRef KubernetesNameRef `json:"portRef"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
PortRef KubernetesNameRef `json:"portRef"`
PortRef KubernetesNameRef `json:"portRef,omitempty"`

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack.

PortID string `json:"portID,omitempty"`

// segmentationType is the type of segmentation used.
// +kubebuilder:validation:MaxLength=1024
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this should match the same validation in spec for this field.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's OK if it's higher in the Status than in the Spec (the opposite is not OK).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack.

Copy link
Collaborator

@mandre mandre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect you haven't used the scaffolding tool. If it's not too much trouble, would it be possible for you to re-work your controller to use it? It ensures consistency with the other controllers and makes it much easier for reviewers to see your modifications, since there's typically a lot of boilerplate code in PRs for new controllers. See #568 (comment) for the rational. I'm currently working on updating the developers doc to make it more obvious.

I bet it was a lot of work to contribute this controller without the help of the scaffolding tool, so if that turns out to be too complicated to rework your change to make use of it, I'm ready to make an exception.

FYI, here's how I expect us to run the scaffolding tool, based on what the resource supports:

go run ./cmd/scaffold-controller \
        -interactive=false \
        -kind Trunk \
        -gophercloud-client NewNetworkV2 \
        -gophercloud-module github.com/gophercloud/gophercloud/v2/openstack/networking/v2/extensions/trunks \
        -import-dependency Port \
        -import-dependency Project \
        -optional-create-dependency Project \
        -required-create-dependency Port

PortID string `json:"portID,omitempty"`

// segmentationType is the type of segmentation used.
// +kubebuilder:validation:MaxLength=1024
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's OK if it's higher in the Status than in the Spec (the opposite is not OK).

@github-actions github-actions bot removed the semver:major Breaking change label Dec 7, 2025
@github-actions
Copy link

github-actions bot commented Dec 7, 2025

Failed to assess the semver bump. See logs for details.

Copy link
Contributor

@winiciusallan winiciusallan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @aldokimi, I've left more comments. This kind of PR tends to be very large, so I'll need to take another look. But for now, thanks for addressing the comments. =D

},
{
Name: "Trunk",
ExistingOSClient: true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please remove this field? This uses an existing client, but we want to separate clients for each controller.

You may remove and run make generate. Maybe do you need to refactor other parts along the code.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I don't really understand why removing this field is necessary, could elaborate more please?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. To be honest, I don't know the exactly reason. I believe @mandre can explain it better.

My guess is, if you need some extra logic for a specific client, you won't impact the others implemented in the same interface. As I said, is just I guess, so don't take it as the truth 😅.

return nil
}

updateOpts.RevisionNumber = &osResource.RevisionNumber
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May the revision number be nil, or does the API always returns a valid value?

yield(nil, err)
}, nil
}
return func(yield func(*osResourceT, error) bool) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same about the comment on ListForAdoption.

@github-actions github-actions bot added the semver:major Breaking change label Dec 18, 2025
@winiciusallan
Copy link
Contributor

winiciusallan commented Dec 19, 2025

@aldokimi I may be a little busy (resting...) in the next few days, so maybe I'll take a little while to review your commits, but at the start of the year, I should take a look into it.

Thanks for contributing, we really appreciate it. =D

@winiciusallan
Copy link
Contributor

Hey @aldokimi, I had some time to take a look into your PR.

It looks like you have overrided your old implementation for Trunk types with the code generated by the scaffolding tool. Are you still working on this? Also, I saw that you changed a lot of tests files from other controllers, I believe we don't want to touch another controllers on this pull request. Do you have made this changes for a specific reason?

If you are still working on this, you can ignore my comment. Let me know when you believe it is ready for another review :)

@aldokimi
Copy link
Author

Hey @aldokimi, I had some time to take a look into your PR.

It looks like you have overrided your old implementation for Trunk types with the code generated by the scaffolding tool. Are you still working on this? Also, I saw that you changed a lot of tests files from other controllers, I believe we don't want to touch another controllers on this pull request. Do you have made this changes for a specific reason?

If you are still working on this, you can ignore my comment. Let me know when you believe it is ready for another review :)

Hello @winiciusallan , I am still going to upload a last commit, the changes on the test files where because of the scaffolding tool, my last commit will be about fixing the issues regarding the scaffolding and then we will be ready for a new review!

Thank you for your comment, happy holidays!

@aldokimi
Copy link
Author

Hello @winiciusallan and @mandre , happy new year!

So, I am sorry for this mess, this is the biggest PR of my life xD
I think now the PR is ready for a new review, if needed I am down for a code review session!

Thanks,

Copy link
Contributor

@winiciusallan winiciusallan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @aldokimi, thanks for taking time to work on it.

I have left a few comments, especially on the API part. This particular part is good overall. Let's see if Martin has comments to make.

I feel that it is missing some logic on the actuator file to handle import, creation and the update of the resource. I avoided adding repetitive comments inline to not make the review cluttered. Are you probably still working on it? If you need to discuss something, I'm online on kubernetes slack workspace, or on the #gophercloud channel.

Happy new year for you too =) 🎆

GOLANGCI_LINT_VERSION ?= v2.7.2
KAL_VERSION ?= v0.0.0-20250924094418-502783c08f9d
MOCKGEN_VERSION ?= v0.5.0
MOCKGEN_VERSION ?= v0.6.0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Martin could give better feedback here, but I believe we should bump mockgen version on a separate PR to better track the changes, if it is really necessary.

// segmentationType is the segmentation type for the subport (e.g. vlan).
// +required
// +kubebuilder:validation:MinLength:=1
// +kubebuilder:validation:MaxLength:=255
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's sticky the maximum length to 32 bytes as the source code defines.

If we set it to 255, the user can pass any value, so the openstack may return a fail code whe trying to get or create the resource. If we stick to the maximum length permitted by the API, we avoid making this unecessary request to the OpenStack API.

Other suggestion is use enumeration, since the only two options are inherit and vlan. We have an example here.

// status indicates whether the trunk is currently operational. Possible values include
// `ACTIVE', `DOWN', `BUILD', `DEGRADED' or `ERROR'. Plug-ins might define additional values.
// +optional
Status *string `json:"status,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please set a maximum length here?

When you don't specify, CEL works by calculating the worst case for that validation, so we always try to set this value, even if it is an estimate. Here it is a talk that explore more about it (thanks Martin).

// tenantID is the project owner of the trunk (alias of projectID in some deployments).
// +kubebuilder:validation:MaxLength=1024
// +optional
TenantID string `json:"tenantID,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although tenant_id is for old Keystone APIs, I believe it won't gonna hurt to have it here.


// tags is a list of Neutron tags to apply to the trunk.
//
// NOTE: ORC does not currently reconcile tag updates for Trunk.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain better why? Is it because the networking API does not support updating the tags for the Trunk port?

If so, I believe it is worth having it annotated here.

Comment on lines +75 to +77
// TODO(scaffolding) If you need to filter resources on fields that the List() function
// of gophercloud does not support, it's possible to perform client-side filtering.
// Check osclients.ResourceFilter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you forgot to delete it? There is others "TODO" comments along this same file.

Description: string(ptr.Deref(filter.Description, "")),
PortID: ptr.Deref(port.Status.ID, ""),
ProjectID: ptr.Deref(project.Status.ID, ""),
// TODO(scaffolding): Add more import filters
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we can add more fields as you declared on types. Status and AdminStateUp are missing. Could you add it please?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

semver:major Breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants