Skip to content

Keystone V3: Fix time elements handling#1937

Merged
jtopjian merged 1 commit intogophercloud:masterfrom
kayrus:some-fixes
Apr 24, 2020
Merged

Keystone V3: Fix time elements handling#1937
jtopjian merged 1 commit intogophercloud:masterfrom
kayrus:some-fixes

Conversation

@kayrus
Copy link
Copy Markdown
Contributor

@kayrus kayrus commented Apr 15, 2020

Resolves #1938
This PR fixes issues in time handling.
Additionally I noticed that there is no error check in baremetal packages.

@kayrus kayrus force-pushed the some-fixes branch 2 times, most recently from cbe0258 to a9dd45f Compare April 15, 2020 18:15
@coveralls
Copy link
Copy Markdown

coveralls commented Apr 15, 2020

Coverage Status

Coverage decreased (-0.002%) to 79.3% when pulling f6a8647 on kayrus:some-fixes into 456b0b6 on gophercloud:master.

@jtopjian
Copy link
Copy Markdown
Contributor

@kayrus Can you please create a corresponding issue that details the changes being made here?

I've been flexible with combining multiple features/fixes in a single PR, but we still need issues to describe why changes are being made.

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 15, 2020

@jtopjian updated

@jtopjian
Copy link
Copy Markdown
Contributor

Thank you!

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 15, 2020

Build failed.

Copy link
Copy Markdown
Contributor

@jtopjian jtopjian left a comment

Choose a reason for hiding this comment

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

@kayrus I've suggested a simpler way of passing the time to the request body - let me know if you have any questions.

In addition, the acceptance tests are failing:

convenience.go:35: �[1;31mFailure in applicationcredentials_test.go, line 94: unexpected error �[0m�[1;33m"parsing time \"\"2119-01-01T12:12:12.000000\"\" as \"\"2006-01-02T15:04:05Z07:00\"\": cannot parse \"\"\" as \"Z07:00\""�[0m�[1;31m�[0m

It appears that the time format being returned is MilliNoZ, which needs the UnmarshalJSON method to be parsed correctly.

}

// MarshalJSON converts our struct request into JSON.
func (opts CreateOpts) MarshalJSON() ([]byte, error) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This can instead be implemented as:

// ToApplicationCredentialCreateMap formats a CreateOpts into a create request.
func (opts CreateOpts) ToApplicationCredentialCreateMap() (map[string]interface{}, error) {
  b, err := gophercloud.BuildRequestBody(opts, "application_credential")
  if err != nil {
    return b, err
  }

  if opts.ExpiresAt != nil {
    appCred := b["application_credential"].(map[string]interface{})
    appCred["expires_at"] = opts.ExpiresAt.Format(gophercloud.RFC3339Milli)
    b["application_credential"] = appCred
  }

  return b, nil
}

This pattern is used in other areas of Gophercloud already.

In addition, we'll need to verify what time format Keystone is expecting. We're using Milli here, but MilliNoZ is being returned - that might cause some confusion and usage errors.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

My idea was to avoid body modification inside the To***CreateMap, but do this in MarshalJSON.

I clarified time format:

  • Trusts accept and return RFC3339Milli, but response truncates milliseconds. Therefore for tests we need to truncate milliseconds.
  • AppCreds accept and return RFC3339MilliNoZ. However for tests we need to truncate nanoseconds.

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 16, 2020

Build succeeded.

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 16, 2020

Build failed.

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 16, 2020

recheck

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 16, 2020

Build succeeded.

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 16, 2020

@jtopjian PR is ready to review. I hope that MarshalJSON is a better approach comparing to type assertion in ToApplicationCredentialCreateMap

@jtopjian
Copy link
Copy Markdown
Contributor

I'd prefer not using MarshalJSON and instead doing the request body amendments within the ToApplicationCredentialCreateMap method. MarshalJSON and ToApplicationCredentialCreateMap have overlap in their capabilities, but ToApplicationCredentialCreateMap is the go-to in Gophercloud for request body amendments.

There are a handful of other areas in Gophercloud that are using MarshalJSON, but I was never comfortable approving them. Conversely, the ToXYZ methods are used frequently throughout Gophercloud and I'd prefer to stick with that.

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 20, 2020

@jtopjian from my perspective To***Map should be used, when MarshalJSON cannot be used, e.g. Extra field in users package is an excellent example:

Or in auth options

func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[string]interface{}, error) {
when you need to create a complex body without altering the original opts structure. Let me know if you agree, and I'll add this info into a contributor guide.

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 20, 2020

Here are the places, where you can use JSONMarshal as well:

if opts.Meta.Expiration != nil {

if opts.Expiration != nil {

if opts.FirstExecutionTime != nil {

@jtopjian
Copy link
Copy Markdown
Contributor

Here are the places, where you can use JSONMarshal as well:

Two of those were written by me and I explicitly chose not to use MarshalJSON 🙂

from my perspective To***Map should be used, when MarshalJSON cannot be used,

I agree that it could be used, but I have to respectfully request that it isn't.

The To*** method patterns are used to build a standard request as well as to modify a request beyond what simple marshalling can do. This is a standard pattern used throughout Gophercloud. By adding another option, MarshalJSON, you break that pattern and provide another choice that can already be solved by using the original pattern.

The opposite is not true: you can't use MarshalJSON for everything that the To*** methods are used for.

In addition, To***Map provides easier interaction with the data. Compare the example I provided in this PR versus having to create a new type and build a new struct - it's much harder to comprehend.

There are a few occurrences of MarshalJSON in Gophercloud and I've often made notes to remove them, but it hasn't really been a pressing issue. Even this discussion we're having now isn't terribly pressing - it's not going to severely hurt the project if MarshalJSON is used, but given the amount of contributions you make to Gophercloud, I'd prefer us having a detailed conversation to ensure we're on the same page for future work.

I understand Gophercloud leverages UnmarshalJSON heavily and so it's understandable to think that if UnmarshalJSON is heavily used, then we should give equal weight to MarshalJSON. Perhaps Gophercloud could/should have a similar ToResultExtractMap method similar to the request methods for consistency - but that's a much larger topic to discuss.

For now, I'd prefer having the rules of:

  1. Use the To*** methods to build a request
  2. Use the UnmarshalJSON method to build a response.

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 20, 2020

@jtopjian thanks for clarification. I'll use To*** method.

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 21, 2020

Build succeeded.

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 23, 2020

Build succeeded.

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 23, 2020

@jtopjian applied fixes

Copy link
Copy Markdown
Contributor

@jtopjian jtopjian left a comment

Choose a reason for hiding this comment

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

LGTM - thank you!

@jtopjian jtopjian merged commit 6917509 into gophercloud:master Apr 24, 2020
@kayrus kayrus deleted the some-fixes branch April 24, 2020 05:47
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.

Keystone V3: Change ApplicationCredentials CreateOpts.ExpiresAt from string to time

3 participants