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

Add Schema examples annotation #580

Merged
merged 13 commits into from Jan 24, 2022
Merged

Conversation

gcheadle-vmware
Copy link
Contributor

@gcheadle-vmware gcheadle-vmware commented Jan 12, 2022

  • include annotation lines in mismatched type error
  • collect mismatched type error all provided examples and return together

Copy link
Contributor

@cari-lynn cari-lynn left a comment

Choose a reason for hiding this comment

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

Great job covering all the possible test cases. I'm really happy with the code added here, and think the description struct is a good way to group these annotations.

One piece for discussion:

There is two different syntax for adding an example WITHOUT a description.

@schema/examples (‘value’,)

@schema/examples (“”, “value”)
Since if the description is “” it will be ignored.

I do like the readability of the second one, I can't imagine a use case where the description needs to be "". But I do wonder if it is a good idea to remove the string just because it is zero value.. 🤔

pkg/schema/annotations.go Outdated Show resolved Hide resolved
@gcheadle-vmware
Copy link
Contributor Author

gcheadle-vmware commented Jan 13, 2022

two different syntax for adding an example WITHOUT a description.

@schema/examples (‘value’,)

@schema/examples (“”, “value”)
Since if the description is “” it will be ignored.

@cari-lynn
I'm glad you pointed this out, I thought that it was not right to add an empty string as the value to the x-example-description key, so I treated the empty string as the default case. I could see a case where a GUI is displaying the example and it's description from an OpenAPI schema, and an author might need to always include the x-example-description key since the GUI checks for it. The author in that case may want the ability to include an empty string?

However the x-example-description key is a custom extension to the OpenAPI spec so this GUI would have to be built specifically for the schema that ytt generates...

@pivotaljohn
Copy link
Contributor

@cari-lynn I'm glad you pointed this out, I thought that it was not right to add an empty string as the value to the x-example-description key, so I treated the empty string as the default case. I could see a case where a GUI is displaying the example and it's description from an OpenAPI schema, and an author might need to always include the x-example-description key since the GUI checks for it. The author in that case may want the ability to include an empty string?

Oh, as having consumed one-to-many APIs where keys disappear when no value is specified, I really appreciate this thinking. Reminds me of the Go Proverb, "Make the zero value useful".

However the x-example-description key is a custom extension to the OpenAPI spec so this GUI would have to be built specifically for the schema that ytt generates...

And it's the nature of maps/dictionaries/key-value pairs that such entries can easily/safely be ignored if not needed. 👍🏻

pkg/cmd/template/schema_author_test.go Outdated Show resolved Hide resolved
pkg/cmd/template/schema_author_test.go Outdated Show resolved Hide resolved
pkg/cmd/template/schema_author_test.go Outdated Show resolved Hide resolved
pkg/cmd/template/schema_author_test.go Outdated Show resolved Hide resolved
pkg/cmd/template/schema_author_test.go Outdated Show resolved Hide resolved

= found: non tuple in @schema/examples (by schema.yml:3)
= expected: tuple with optional string description and required example value
= hint: use a trailing comma to construct tuple with a single value. e.g. ('example value',)
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 would be a non-empty description with a None value...?

I think you mean to hint: (, "example value")

Copy link
Contributor

Choose a reason for hiding this comment

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

(I looked into this a bit so im commenting what I found) I thought ('example value',) was odd too. But I believe the trailing comma is the correct syntax. That makes it a single-element tuple. I believe the leading comma syntax isn't supported.
https://wiki.python.org/moin/TupleSyntax#:~:text=Multiple%20Element%20Tuples&text=Multiple%2Delement%20tuples%20may%20be,be%20enclosed%20in%20parentheses%2C%20e.g.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See comment below about disallowing this for now.

pkg/schema/annotations.go Outdated Show resolved Hide resolved
pkg/schema/annotations.go Outdated Show resolved Hide resolved
pkg/schema/annotations.go Show resolved Hide resolved
GetTitle() string
GetExample() (string, interface{})
SetDocumentation(documentation)
Copy link
Contributor

Choose a reason for hiding this comment

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

This signature will make it not possible for code outside of schema to be able to set documentation...

... have you already considered providing setters for Title and Description and then maybe something like AddExample(..)? or SetExamples(...)?

Related:

  • Today, we can only use the first example in OpenAPI v3.0 output
  • But when we turn around and support OpenAPI v3.1 (and that will happen), we'll want to be able to store multiple examples.
  • Also, we'd love to be able to support multiple examples in ytt Schema, today; no need to limit that part of these system.
  • Consider what happens when we push the limitation right up to the seam where it's introduced (i.e. when building the OpenAPI output).

@cari-lynn
Copy link
Contributor

I thought that it was not right to add an empty string as the value to the x-example-description key, so I treated the empty string as the default case

I can see adding the x-example-description key adding noise to an already dense schema and not a lot of value.

And it's the nature of maps/dictionaries/key-value pairs that such entries can easily/safely be ignored if not needed. 👍🏻

Forgive me for being thick-skulled, do you mean that the empty string in the case of ("", "value") can be ignored if not needed or do you mean that OpenAPI schema consumers can ignore x-example-description if not needed?

For users that want to create a tuple without a description we could encourage users to use the ('example value',) syntax, while having the ('', 'example value') syntax behave as predicted and add x-example-description: "".

@cari-lynn
Copy link
Contributor

One more thing I was experimenting with is using a yamlFragment in the annotation to clean things up:

#@schema/examples func()

But I believe there is no way to specify a tuple in yaml.. which makes abstracting this to a function not possible using yamlFragements.

@pivotaljohn
Copy link
Contributor

GC: I thought that it was not right to add an empty string as the value to the x-example-description key, so I treated the empty string as the default case

CLD: I can see adding the x-example-description key adding noise to an already dense schema and not a lot of value.

I agree that if its not typically used, it's more noise than signal. But by making it optional (i.e. sometimes present, sometimes not), makes that "API" a bit more complicated to use (noted, below).

JSR: And it's the nature of maps/dictionaries/key-value pairs that such entries can easily/safely be ignored if not needed. 👍🏻

CLD: Forgive me for being thick-skulled, do you mean that the empty string in the case of ("", "value") can be ignored if not needed or do you mean that OpenAPI schema consumers can ignore x-example-description if not needed?

The latter: that it's (usually) easy to ignore an entry in a map. I'm drawing an analogy with JSON APIs: that it makes for an easier interface to program to when every time there's an example: property, it always has an x-example-description... even if an empty string. It's analogous to a field that's zero vs. not present/defined.

For users that want to create a tuple without a description we could encourage users to use the ('example value',) syntax, while having the ('', 'example value') syntax behave as predicted and add x-example-description: "".

Wouldn't that mean that sometimes the first element in the tuple is the example value and other-times it would be the second element in the tuple?

@gcheadle-vmware
Copy link
Contributor Author

After syncing with John, I decided to go with a simpler design for the annotation, where the description and example are always required. If the user does not want to include a description, they can just provide an empty string and the x-example-description key will just have an empty string.

@cari-lynn
Copy link
Contributor

Commenting here to wrap up the threads I started.

[pivotalJohn] it always has an x-example-description... even if an empty string

Sounds good. I agree with the decisions above 👍 If we hear from users that this is noisy, in the future we can add a flag or syntax to omit this.

[me] But I believe there is no way to specify a tuple in yaml.. which makes abstracting this to a function not possible using yamlFragements.

I am satisfied with being able to use a syntax to declare the example in a yamlFragment, and not necessarily being able to declare the entire tuple in a yamlFragment. Eg:
#@schema/example ("host", hostExample())

Thank you!!

- simplify example API to always require string description and valid example
- accept null as a valid example value for nullable data values
- reword error messages
@gcheadle-vmware
Copy link
Contributor Author

@pivotaljohn, @cari-lynn - changes made to type interface to reflect the conversation earlier today.

Copy link
Contributor

@pivotaljohn pivotaljohn left a comment

Choose a reason for hiding this comment

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

Looks great, @gcheadle-vmware.

Note the minor interaction with #582 — there's a hint in here that (should) go away when it merges.

Will leave it to you to decide which order you want these merged to minimize the effort on your part. Ping me if you want a buddy in that.


= found: integer (by schema.yml:3)
= expected: boolean (by schema.yml:4)
= hint: is the default value set using @schema/default?
Copy link
Contributor

Choose a reason for hiding this comment

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

Just note: the hint is misplaced and is fixed in #582. This is a new instance of the hint and will need to be removed after that PR is merged.

@gcheadle-vmware gcheadle-vmware merged commit a5dfa11 into develop Jan 24, 2022
@gcheadle-vmware gcheadle-vmware deleted the schema-examples-annotation branch January 24, 2022 23:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants