Skip to content
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: Fabric stream resource and data sources #844

Merged
merged 13 commits into from
Feb 3, 2025

Conversation

thogarty
Copy link
Contributor

@thogarty thogarty commented Jan 24, 2025

Using terraform-plugin-framework; added the following:

  • equinix_fabric_stream resource
  • equinix_fabric_stream data source
  • equinix_fabric_streams data source

Included automated testing and docs creation leveraging description on schemas

NOTE: Fixed usage of context within Fabric client creations and updated all usages in SDKv2 as well

ClientSecret: c.ClientSecret,
BaseURL: c.BaseURL,
}
authClient := authConfig.New(ctx)
Copy link
Contributor

@ctreatma ctreatma Jan 27, 2025

Choose a reason for hiding this comment

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

Can you remind me why this change is needed? Continuing to use a shared auth client across all API clients would be ideal, but IIRC there's an issue with the shared client using a canceled context, maybe? We should make sure those issue details are captured somewhere so we can work on replacing or at least refactoring the Equinix oauth2-go library in a way that allows sharing auth across clients.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So before we had a different change outlined in the EPT draft: https://github.com/equinix/terraform-provider-equinix/pull/745/files#diff-54c7c1af5fa8d5db4dc49f0e8e80e93ba2b1183ba4d5c9e2e5729e6deae6a3cd

We discussed a few things. One of them was if we were going to use the context in both that we should update all callers (like we are doing here) and the other was to keep the old method along with the new one.

The issue with not passing context for Framework is that there's a canceled context in the config when using the Interface methods that requires passing context to complete those flows.

My theory is that for SDKv2 they shared the same context as the config long enough that it wasn't an issue; but the change resolves that even if it was separate because each lifecycle method passes a usable context into it.

TL;DR, Framework requires context. SDKv2 didn't but changing it so that it uses it doesn't create a problem.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, the framework issue is the one I was thinking of. While this change replicates what is happening for framework, which means it's not necessarily introducing new behavior, my concern is that we're creating a bunch of separate auth clients that are going to be using the same client ID and secret but not using the same token. The SDKv2 clients previously shared the same auth client, which reduces the number of token requests across resources, but because of how equinix/oauth2-go is written, the auth client needs a context. The framework doesn't have a suitable context for that, so we got those canceled context errors. It's not necessarily a problem to replicate the framework behavior in SDKv2, but going all-in on duplicate auth clients means we'll be making even more unnecessary token requests (two resources using the same client ID & secret each have to make their own token request even though their tokens will have the same permissions). Duplicate requests could become a problem (or at least a complication) if, for example, rate limits are introduced on the token endpoint. Long-term it would be preferable to change our approach to auth clients in the terraform provider so that tokens can be reused across API clients.

To be clear I'm on board with this change as-is; we might have to standardize on accepting a context anyway in order to make the optimization I described, whenever that time comes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I was able to follow this explanation through to the end on this one. Initially my confusion on context was distracting me from the token issue; I only partially understood what might have been happening. Now that I've got a better handle on the context cancellation issue the auth client separation per resource is clear.

We're on the same page now. Thank you for a very thorough explanation, @ctreatma!

}
}

output "stream_state" {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need more outputs in this data source ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a resource, and no. We can limit the amount that we provide outputs in examples for maintenance reasons. We just need some display of attribute selection.

}
}

output "number_of_returned_streams" {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here. Do we need to add any other outputs here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same explanation for output.

resource.TestCheckResourceAttr("data.equinix_fabric_streams.data_streams", "pagination.limit", "2"),
resource.TestCheckResourceAttr("data.equinix_fabric_streams.data_streams", "pagination.offset", "1"),
),
ExpectNonEmptyPlan: true,
Copy link
Contributor

Choose a reason for hiding this comment

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

If the plan is empty, this test will fail. ExpectNonEmptyPlan: false would keep it consistent with other tests (for other resources)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is set specifically to allow the test to pass for my use case. I do expect a non-empty plan after my tests run. You can actually omit ExpectNonEmptyPlan: false as well because that's the default value for that config item.

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay. Sounds good.

}
*project = fwtypes.NewObjectValueOf[ProjectModel](ctx, &projectModel)

const TIMEFORMAT = "2006-01-02T15:04:05.000Z"
Copy link
Contributor

Choose a reason for hiding this comment

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

The naming convention in Go for unexported constants is camelCase. const timeFormat

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Learned something new! There are other places where we use the non-idiomatic Go styling for constants so we can update them with the same reference as well.

Good to cite it also: https://google.github.io/styleguide/go/guide.html#mixedcaps

Copy link
Contributor

Choose a reason for hiding this comment

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

If we're adopting or changing coding standards, that should be reflected in the linter settings to enforce convergence on the chosen style.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, so I went through this thoroughly. I was mistaken, we don't really have any other places that all caps were used for variable names. We have camelCase throughout.

Additionally, even when adding stylecheck to the linter it doesn't care about all caps in a variable name. There isn't a Go style descriptor against all caps.

I'm going to leave it out of the linter for now, and I'll move this into the internal/fabric package so that it can be reused, because we'll have it in several places for the Framework implementations of fabric's new resources.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Update made 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, it's running through all files because of the config change...

We're bottle necking a bit here because of this. All files introduced by this change pass the linters. The files changed for config are not compliant.

I'm going to remove the linter update for this one, then add in separate PR. Then when we are poking around for one-off fixes or updates from SDKv2 to Framework we can make necessary updates. It's too much time for the current scope we're on.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Opened #849

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@d-bhola + @ctreatma ready for final review 👍

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, it's running through all files because of the config change...

This is true of the make lint task for running linters locally, but not the case for PR validation in GitHub (if the config change were made in this PR, the GitHub Actions workflow would only lint the changes in this PR, not the full codebase...but personally I still think it's better to update config separately). Last year, the plan was to eventually make PR validation lint the full codebase, but IMO linter config changes are a good reason to keep the limited PR linting indefinitely, in which case we may want to figure out how to update the local make lint task to more closely match the PR validation behavior.

Copy link
Contributor Author

@thogarty thogarty Feb 3, 2025

Choose a reason for hiding this comment

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

Sorry, I should have been more clear. It's not linting the entire project, but because we updated all of the SDKv2 Fabric resources/datasources files to use the config.go update change to pass their context in; all of those files are being linted also even though they're not the target of this PR directly.

So to resolve all Fabric linter errors in this project is overkill for this PR. Which is why I've separated out the linter to a different PR while also ensuring the new Streams additions are adherent to it by running make lint locally.


func testSweepStreams(region string) error {
var errs []error
log.Printf("[DEBUG] Sweeping Fabric Streams")
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need this logging statement here ? If it's for debugging, should we remove it ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In test output it will show up and provide useful data for the state of sweepers when run.


for _, stream := range streams.GetData() {
if sweep.IsSweepableFabricTestResource(stream.GetName()) {
log.Printf("[DEBUG] Deleting stream: %s", stream.GetName())
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here. Do we need this logging statement here ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same explanation; In test output it will show up and provide useful data for the state of sweepers when run.

@d-bhola
Copy link
Contributor

d-bhola commented Jan 29, 2025

Needs rebase

@thogarty thogarty force-pushed the fabric_stream_resource_and_data_sources branch from b8a6440 to f485a2b Compare January 29, 2025 22:49
d-bhola
d-bhola previously approved these changes Jan 29, 2025
Copy link
Contributor

@d-bhola d-bhola left a comment

Choose a reason for hiding this comment

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

LGTM

@codecov-commenter
Copy link

codecov-commenter commented Jan 31, 2025

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

Attention: Patch coverage is 2.18712% with 805 lines in your changes missing coverage. Please review.

Project coverage is 33.96%. Comparing base (c71308e) to head (a8f8962).
Report is 24 commits behind head on main.

Files with missing lines Patch % Lines
internal/resources/fabric/stream/resource.go 0.00% 204 Missing ⚠️
...rnal/resources/fabric/stream/datasources_schema.go 0.00% 164 Missing ⚠️
...nternal/resources/fabric/stream/resource_schema.go 0.00% 125 Missing ⚠️
internal/resources/fabric/stream/models.go 0.00% 121 Missing ⚠️
.../resources/fabric/stream/datasource_all_streams.go 0.00% 41 Missing ⚠️
.../resources/fabric/stream/datasource_by_streamid.go 0.00% 34 Missing ⚠️
internal/resources/fabric/stream/sweeper.go 0.00% 33 Missing ⚠️
internal/config/config.go 52.63% 9 Missing ⚠️
equinix/resource_fabric_service_profile.go 0.00% 8 Missing ⚠️
equinix/resource_fabric_cloud_router.go 0.00% 7 Missing ⚠️
... and 19 more

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #844      +/-   ##
==========================================
- Coverage   36.13%   33.96%   -2.18%     
==========================================
  Files         184      187       +3     
  Lines       24491    24846     +355     
==========================================
- Hits         8850     8438     -412     
- Misses      15480    16283     +803     
+ Partials      161      125      -36     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

…ations in as many files as this change is touching
max-same-issues: 0
Copy link
Contributor

Choose a reason for hiding this comment

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

This whitespace change in the linter config is tagging DRE for review; if you revert this change then you'll only need review/approval from @d-bhola.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh wait, I'm wrong; the changes to config.go are technically shared, so that requires separate sign-off either way; taking care of that now.

@thogarty thogarty merged commit fc4011e into main Feb 3, 2025
9 of 12 checks passed
@thogarty thogarty deleted the fabric_stream_resource_and_data_sources branch February 3, 2025 22:13
Comment on lines +173 to +177
func parseStream(ctx context.Context, stream *fabricv4.Stream,
streamType, name, description, href, uuid, state *basetypes.StringValue,
assetsCount, streamSubscriptionCount *basetypes.Int32Value,
project *fwtypes.ObjectValueOf[ProjectModel],
changeLog *fwtypes.ObjectValueOf[ChangeLogModel]) diag.Diagnostics {
Copy link
Contributor

Choose a reason for hiding this comment

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

I missed this at review time, but this pattern of defining a shared parseThing(...) function for separate models should not be followed any more. It was a workaround for the fact that terraform-plugin-framework did not support embedded structs when we started adopting it. The framework supports embedded structs now, which means we can reuse the thing.parse(data) function across different model types for more idiomatic Go code. #853 is an example of that change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy that! Will follow.

Copy link

This PR is included in version 3.2.0 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants