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

Decaf endpoints #223

Merged
merged 41 commits into from
Dec 31, 2024
Merged

Decaf endpoints #223

merged 41 commits into from
Dec 31, 2024

Conversation

alextwoods
Copy link
Contributor

@alextwoods alextwoods commented Dec 16, 2024

Description of changes:

Changes in smithy-client:

  • Remove Endpoints plugin - this is instead code generated per service.
  • Add rules engine stdlib functions. (copied from hearth).
  • Add jmespath as a dependency (used by endpoint parameter bindings).

Changes in smithy:

  • Codegeneration for:
    • endpoint parameters
    • endpoint provider/resolver
    • endpoint plugin
    • endpoint provider specs (translate endpoint test cases).
  • extension points for register endpoint built in bindings and stdlib functions.
  • default weld that adds default endpoint rules/tests.
  • All Endpoint2.0 test models.
  • Task to generate sdk per test model + run specs (added to CI).

Not part of this PR (future work):

  • OperationInput tests (ie, E2E endpoint tests of the client. Requires being able to make client operation calls)
  • Endpoints + Auth. (requires us to implement Auth schemes/resolver, ect).

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@alextwoods alextwoods requested a review from mullermp December 16, 2024 23:45
gems/smithy/lib/smithy/anvil/endpoint_parameter.rb Outdated Show resolved Hide resolved
gems/smithy/lib/smithy/anvil/views/client/module.rb Outdated Show resolved Hide resolved

# Endpoint BuiltInBinding
class BuiltInBinding
def initialize(id:, render_config:, render_build:, render_test_set:)
Copy link
Contributor

Choose a reason for hiding this comment

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

I've just been using options = {} everywhere because of how easy it is to just pass options down the line without extracting keyword args... Not sure how you feel about that. I think I lean towards keyword args for required public interfaces.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah - I think for required public interfaces I'd generally prefer keyword args. Since this is an extension point/public interface, I think keeping them as keywords make sense.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this is public at all. Please just use options for vise usage. But I think these are better used as view classes now - since vise does not have any shape wrapping.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These must be public - these are the extension point for users to add endpoint related bindings.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've removed the classes and just using arrays/hashes.

gems/smithy/lib/smithy/welds/endpoints.rb Outdated Show resolved Hide resolved
[Vise::Endpoints::BuiltInBinding.new(
id: 'SDK::Endpoint',
render_config: proc do |_plan|
<<-ADD_OPTION
Copy link
Contributor

Choose a reason for hiding this comment

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

I've been using ~ with indentation. I think you can make this a method that takes option values. Custom options come from the endpoint params but static values for endpoint.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can switch to <<~ for indentation - I don't have a style preference on those.

What do you mean about having this method take option values. I'm not quite sure I understand.

In general, this needs to be fairly flexible to support all of our existing/future built ins (eg: account id).

Copy link
Contributor

Choose a reason for hiding this comment

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

This still needs to be indented. What I was saying before was to have a method that is responsible for rending the config, but this is fine to hardcode endpoint for now. Eventually this will need to be a method.

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 the correct indenting for it to render correctly in the generated code.

Why should this be a method? I think I'm still a little confused about that. Using a proc/callable is what lets a user define arbitrary configuration(s) that may apply for the builtin. I think thats perferable to coming up with a codegen time modeling of config.

gems/smithy/lib/smithy/welds/endpoints.rb Outdated Show resolved Hide resolved
gems/smithy/lib/smithy/welds/endpoints.rb Outdated Show resolved Hide resolved
Copy link
Contributor

@jterapin jterapin left a comment

Choose a reason for hiding this comment

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

May want to run rubocop to fix some indentations.


attr_reader :scheme, :authority, :path, :normalized_path, :is_ip

def as_json(_options = {})
Copy link
Contributor

Choose a reason for hiding this comment

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

Curious to know why _options = {} is necessary than omitting it. I'm guessing it is due to the way this class is used as a "wrapper" for URI?

Copy link
Contributor Author

@alextwoods alextwoods Dec 17, 2024

Choose a reason for hiding this comment

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

good question, I guess we could use * or ... instead to indicate it can take arguments, but doesn't use them.

Edit, I've updated to use just *.

gems/smithy-client/lib/smithy-client/endpoint_rules.rb Outdated Show resolved Hide resolved
gems/smithy/lib/smithy/anvil/endpoint_parameter.rb Outdated Show resolved Hide resolved
gems/smithy/lib/smithy/anvil/endpoint_parameter.rb Outdated Show resolved Hide resolved
gems/smithy/lib/smithy/tools/underscore.rb Show resolved Hide resolved
@alextwoods alextwoods changed the title [WIP]Decaf endpoints Decaf endpoints Dec 26, 2024
@alextwoods alextwoods marked this pull request as ready for review December 26, 2024 18:51
.github/workflows/ci.yml Outdated Show resolved Hide resolved
Rakefile Outdated Show resolved Hide resolved
gems/smithy-client/lib/smithy-client/endpoint_rules.rb Outdated Show resolved Hide resolved
gems/smithy-client/lib/smithy-client/endpoint_rules.rb Outdated Show resolved Hide resolved
[Vise::Endpoints::BuiltInBinding.new(
id: 'SDK::Endpoint',
render_config: proc do |_plan|
<<-ADD_OPTION
Copy link
Contributor

Choose a reason for hiding this comment

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

This still needs to be indented. What I was saying before was to have a method that is responsible for rending the config, but this is fine to hardcode endpoint for now. Eventually this will need to be a method.

gems/smithy/lib/smithy/welds/endpoints.rb Outdated Show resolved Hide resolved
gems/smithy/lib/smithy/welds/endpoints.rb Outdated Show resolved Hide resolved
@@ -0,0 +1,319 @@
{
Copy link
Contributor

Choose a reason for hiding this comment

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

Are there .smithy file equivalents we should copy in too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I guess - they're in AwsDrSeps. I'm not sure I like this mixed model.json/model.smithy we have going for our test fixtures, though I'm not quite sure what we should do.

Copy link
Contributor

Choose a reason for hiding this comment

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

I find it easier to edit the model files in smithy IDL then generate the json with it, that's why both are there. We could require smithy cli and shell out to convert to AST and not have the json, but also having the json inspectable (in the folder) helps with writing generation.

Copy link
Contributor

@mullermp mullermp left a comment

Choose a reason for hiding this comment

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

Nice!

include_paths = []
tmp_dirs = []
Dir.glob('gems/smithy/spec/fixtures/endpoints/*/model.json') do |model_path|
test_name = model_path.split('/')[-2]
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a better way to express this one?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you mean the model_path.split('/')[-2] part? I could do model_path.split('/').last(2).first instead, but that felt worse. Alternatively we coudl use regex to extract it, but I think splitting on / is simpler here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Was thinking in terms of readability. What exactly is extracted? It's otherwise fine.

gems/smithy-client/lib/smithy-client.rb Outdated Show resolved Hide resolved
gems/smithy-client/lib/smithy-client/base.rb Outdated Show resolved Hide resolved
gems/smithy/lib/smithy/anvil/client/endpoint_parameter.rb Outdated Show resolved Hide resolved
@@ -24,6 +24,7 @@ def forge

private

# rubocop:disable Metrics/AbcSize
Copy link
Contributor

Choose a reason for hiding this comment

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

I added the methods here to solve this but I guess it was just deferred. Is there a way to solve this one? Maybe if enumerator is passed to a method and that method does the yielding? Otherwise I guess it's fine to just ignore this one as it's a giant list.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, its just a list so I don't think rubucop is useful for that... We could solve it by breaking it into even more methods, but I dont think that really helps readability.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah. In that case the multimethods are kinda unnecessary.

e.yield "lib/#{@gem_name}/plugins/endpoint.rb", render_endpoint_plugin

e.yield 'spec/spec_helper.rb', render_spec_helper
e.yield 'spec/endpoint_provider_spec.rb', render_endpoint_provider_spec
Copy link
Contributor

Choose a reason for hiding this comment

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

I think by convention this should still be spec/gemname/specs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Was following what we had in V3, but I can update.

def endpoint_built_in_bindings
{
'SDK::Endpoint' => {
# Text indenting is used in generated view.
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be better if indenting was relative instead of absolute here. So, using <<~ADD_OPTION with one level of indenting, then in our view, apply the current indenting level plus this one level.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm struggling with this because of the multiline text. Is there a way to have erb views indent multiline text?

smithy-build.json Outdated Show resolved Hide resolved
@alextwoods alextwoods merged commit 74e8854 into decaf Dec 31, 2024
3 checks passed
@alextwoods alextwoods deleted the decaf_endpoints branch December 31, 2024 00:34
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.

3 participants