support for feature l2connection PrimaryZSideServiceToken#8
support for feature l2connection PrimaryZSideServiceToken#8
Conversation
|
This field is documented at https://developer.equinix.com/docs/fabric-connect-using-service-token-parameters-mapping This PR is in support of equinix/terraform-provider-equinix#223 |
| //since service tokens are created at port level and not through an SP, and SPs are always | ||
| //the z-side of the connection, so in that case service token can only be used for the a-side. | ||
| var serviceToken, zSideServiceToken *string | ||
| if getResponse.SellerServiceUUID != nil || getResponse.AuthorizationKey != nil { |
There was a problem hiding this comment.
Is there a reason to create a second service token field in the SDK (diverging from the API spec) when only one field will ever be set?
Should we keep the response object the same (matching the upstream API spec) and include a helper for this detection?
// IsZside determines if a connection is a zSide connection.
// This is especially helpful in determining if the ServiceToken (when present) is a zSide token.
func (l *L2Connection) IsZside() bool {
return ! (l.SellerServiceUUID != nil || l.AuthorizationKey != nil)
}(probably want to reverse the logic to avoid the double negatives)
return l.SellerServiceUUID == nil && l.AuthorizationKey == nilThere was a problem hiding this comment.
Alternatively, this helper could be left up to the user (TF) to implement.
There was a problem hiding this comment.
The reason was that API POST request have them both, while GET just vendorToken, it simplifies the interface, otherwise the L2Connection object will require three attributes
type L2Connection struct {
...
ServiceToken *string
ZSideServiceToken *string
VendorToken *string
}
However, I agree we don't want this to diverge from API, but ServiceToken was already used in prev releases to return a-side token. Is that a problem?
There was a problem hiding this comment.
I think I see. This is the intermediary type that represents the Terraform interface?
This approach makes sense if the intent is to create two separate fields in Terraform.
I'll throw the question back to you - does that improve the Terraform experience? What does it look like one way or the other?
There was a problem hiding this comment.
I think there was a misunderstanding in my prev answer. API has both fields primaryServiceToken and primaryZsideServiceToken in the POST request, despite the fact that just one of them can be applied (maybe something that will change on the future), and GET doesn't have those fields but vendorToken, so I expect same behavoir in the sdk. Even if we keep a single token field, I would like to hold the information in some way to know if it was a-side or a z-side, It can be relevant for users. Below there are some of the options that come to my mind for the terraform side.
Option 1 - Applying all logic at sdk level:
//Create
if v, ok := d.GetOk("service_token"); ok {
primary.ServiceToken = ecx.String(v.(string))
}
if v, ok := d.GetOk("zside_service_token"]); ok {
primary.ZSideServiceToken = ecx.String(v.(string))
}
//Read
if err := d.Set("service_token"], primary.ServiceToken); err != nil {
return fmt.Errorf(err)
}
if err := d.Set("zside_service_token"], primary.ZSideServiceToken); err != nil {
return fmt.Errorf(err)
}
Option 2 - Using IsZside and TF just a single "service_token" attr. We don't modify GET output, so serviceToken/zsideServiceToken will be empty, but user (TF) can use IsZside. There's a problem with this approach (not for TF since it will just set nil in d.Set(...) ), it assumes connection was created using a token, but token is just one of the options. I mean, if vendorToken is nil, isZside can still return true/false.
This will also require extra validations in TF create function, since a-side and z-side have different limitations, for example z-side tokens aren't available for redundant/secondary connections, otherwise just leave API returns back an error.
//Create
if v, ok := d.GetOk("service_token"); ok {
primary.ServiceToken = ecx.String(v.(string))
}
//Read
if primary.IsZside && err := d.Set("service_token"], primary.ZSideServiceToken); err != nil {
return fmt.Errorf(err)
} else if err := d.Set("service_token"], primary.ServiceToken); err != nil {
return fmt.Errorf(err)
}
Option 3 - Same behavior API/SDK/TF - No update service_token/zside_service_token in read func, expose vendorToken (computed) in SDK and in TF the schema:
//Create
Same as opt. 1
//Read
if err := d.Set("vendor_token"], primary.VendorToken); err != nil {
return fmt.Errorf(err)
}
Option 4 -No logic at all, just use the previous value in the schema for service_token/zside_service_token in read func. This option breaks TF import
//Create
Same as opt. 1
//Read
N/A
There was a problem hiding this comment.
IMO, option1 or option3 are best approach for terraform. Option3 is the way for auto-gen sdks and/or TF modules, matching behavior across API and consumers, option1 looks more like the expected user experience (but in this case will differ from API), so if attribute was "service_token" then taking back value from API It should use same attribute and not another computed argument having same value
There was a problem hiding this comment.
I just found out that a-side can be used to connect to your own port using e-line ( although I don't know if makes sense), so looking just for service provider fields is no guarantee of a-side. I see tokenCustOrgId in z-side requests but I'm not sure if it will always come. Tthis makes option 3 the most reliable
…en and match API behavoir
| RedundancyGroup: getResponse.RedundancyGroup, | ||
| Actions: mapL2ConnectionActionsAPIToDomain(getResponse.ActionDetails), | ||
| ServiceToken: getResponse.VendorToken, | ||
| VendorToken: getResponse.VendorToken, |
There was a problem hiding this comment.
Let's be sure to call this out as a breaking change, "L2Connection.ServiceToken has been renamed to VendorToken" (or we can deprecate the old field and set the response value to both field names).
There was a problem hiding this comment.
Err, I see the field is still present, but it no longer receives a value. Is that the intent? Should we deprecate the field? Is there a response value that should be copied here?
There was a problem hiding this comment.
L2Connection is shared across the different interfaces of the client, ServiceToken/ZSide ServiceToken must be there for the POST
Lines 44 to 45 in 52abbf7
I can keep ServiceToken = getResponse.VendorToken with a deprecation note but not sure what is the right way for that more than what I can set in the changelog
There was a problem hiding this comment.
Maybe something like this:
// ServiceToken something something
// Starting with v2.3.0, this field will not be populated with …, see VendorToken for that. The previous behavior was to …
ServiceToken *string
Feature required to support z-side service token.
As described in code both a-side/z-side are returned in
vendorTokenattribute. A little logic has been implemented to distinguish a-side/z-side tokens.