-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Update FSM config parser #3586
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
base: main
Are you sure you want to change the base?
Update FSM config parser #3586
Conversation
| /** | ||
| * Get service-specific endpoint URL for a given profile and service. | ||
| */ | ||
| const Aws::String* GetServiceEndpointUrl(const Aws::String& profileName, const Aws::String& serviceId) const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are we returning a pointer to a string? we should likely be returning by value and rely on RVO or NVRO, or returning bt ref if we actually want to edit the owned string, but we dont want to be returning by pointer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated by using Aws::Crt::Optional<Aws::String> instead of pointer returns.
| return iter->second; | ||
| } | ||
|
|
||
| inline const Aws::String& GetServicesName() const { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why return are we returing by ref? we definitely should not be editing the underlying value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above. Updated to use Aws::Crt::Optional<Aws::String>
| inline const Aws::String& GetServicesName() const { | ||
| auto iter = m_allKeyValPairs.find("services"); | ||
| static const Aws::String empty; | ||
| return (iter != m_allKeyValPairs.end()) ? iter->second : empty; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This likely not how we should be returning the idea of "lack of service endpoint". likely Crt::Optional is a good candidate for representing "lacking of value" instead of empty string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above. Updated to use Aws::Crt::Optional<Aws::String>
|
|
||
| // New service block: "s3 =" (right hand side empty) | ||
| if (!left.empty() && right.empty()) { | ||
| activeServiceId = StringUtils::ToLower(left.c_str()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from the spec
This transformation MUST replace any spaces in the service ID with underscores and uppercase all letters
so ToLower here I think should be ToUpper no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed normalization to use ToUpper
| auto profileIter = m_profiles.find(profileName); | ||
| if (profileIter == m_profiles.end()) | ||
| { | ||
| return nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah dont use "nullptr" to denote absence of a value, or a failed outcome, use a optional, or result type for that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above. Updated to use Aws::Crt::Optional<Aws::String>
| /** | ||
| * Get global endpoint URL for a given profile. | ||
| */ | ||
| const Aws::String* GetGlobalEndpointUrl(const Aws::String& profileName) const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright i think we have a slightly larger design problem here that we should deal with lets take a look at the two new added APIS
Aws::String GetServiceEndpointUrl(const Aws::String& profileName,
const Aws::String& serviceId) const;
Aws::String* GetGlobalEndpointUrl(const Aws::String& profileName) const;both of these functions have something in common, they take a profileName, and even in the comments you mention there is a mapping between profile and endpoint urls. This says to me instead of maintaining a foreign key mapping via this API, this is something that should exist in the profile object, i.e. Profile . so instead of adding this api, lets add this data to the Profile object that we store.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved GetEndpointUrl() and GetServicesName() as computed getters in the profile object, also added a static helper that does the lookup for the service.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NVM on the static helper, removed it!
I was only using it as a temporary 'resolver' for the new unit tests anyways
| private: | ||
| Aws::String m_fileName; | ||
| bool m_useProfilePrefix; | ||
| Aws::Map<Aws::String, Aws::Map<Aws::String, Aws::String>> m_services; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i dont think this is being used anymore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed this map in new commit
| return iter->second; | ||
| } | ||
|
|
||
| inline Aws::Crt::Optional<Aws::String> GetServicesName() const { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so i still think this is the wrong API, the profile object will have a services section, once loaded, we wont be doing any further look ups or joining of the services section and the profile sections, from the outside a API caller will see a profile object, just not it will have a services section/global endpoint member
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to have the profile to include a service object that will contain the map of endpoints and service block name
| auto value = StringUtils::Trim(line.substr(equalsPos + 1).c_str()); | ||
| currentKeyValues[key] = value; | ||
| continue; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we not handling global endpoint URL's for all services?
Ex.
[profile dev-global]
endpoint_url = https://play.min.io:9000
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
global endpoint URL is handled by the FlushSection, and added directly to the profile
| const auto& endpoints = services.GetEndpoints(); | ||
| ASSERT_EQ(1u, endpoints.size()); | ||
| ASSERT_EQ("http://foo.com", endpoints.at("S3")); | ||
| } No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious what the behavior would be if we have multiple endpoint_url key/values in a profile or service configuration. I think we should add tests for scenarios like
[profile dev-global]
endpoint_url = https://play.min.io:9000
endpoint_url = https://play2.min.io:9000
[services s3test]
s3
endpoint_url = https://play.min.io:9000
s3
endpoint_url = https://play2.min.io:9000
From my understanding of the implementation, I think we'd just override the the value, so we'd end up with endpoint_url = https://play2.min.io:9000, but it's probably worth discussing if we want to error out here.
Either way this behavior is likely specific to OUR implementation since the SEP doesn't explicitly define this behavior, and this will be important to catch any regressions if we move to the CRT parser later on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the current parser it will just overwrite the url with the latest endpoint_url, I will add two tests for this behavior
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mentioned some minor fixes before your ship, but API wise looks good
| inline void SetServices(Services&& services) { m_services = std::move(services); } | ||
|
|
||
| inline Aws::Crt::Optional<Aws::String> GetGlobalEndpointUrl() const { | ||
| const Aws::String& endpoint = GetValue("endpoint_url"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the only Get function that uses GetValue, why not create a memeber of profile endpointUrl to be like all the other data members of Profile?
Add support for parsing [services] sections with service-specific endpoint_url configuration following AWS SDKs & Tools specification. Changes: - Extend Profile class with endpoint_url and servicesEndpointUrl map - Add FSM states for [services] and [services serviceId] sections - Add GetServiceEndpointUrl() and GetGlobalEndpointUrl() API methods - Support case-insensitive service ID lookup - Add comprehensive test coverage Supports config format: [profile default] endpoint_url = https://global.example.com [services s3] endpoint_url = http://localhost:9000 Add Profile computed getters using Aws::Crt::Optional for proper null handling: - GetServicesName() returns services definition name or empty Optional - GetEndpointUrl() returns global endpoint URL or empty Optional - Add static Profile::GetServiceEndpointUrl() helper for endpoint resolution - Takes profile, services map, and serviceId as parameters - Maintains Profile as stateless data container - Add AWSConfigFileProfileConfigLoader::GetServices() const accessor Uses Aws::Crt::Optional instead of empty strings to properly represent "no value" state. Static helper pattern keeps Profile ABI-stable while enabling service endpoint resolution without coupling to loader internals. added a test for multiple services definition updated test to use .find before creatng the profile update to use a service object instead of using getvalue added 3 more tests verifying duplication urls, modify the services object with more encapsulation
Add support for parsing [services] sections with service-specific endpoint_url configuration following AWS SDKs & Tools specification.
Issue #, if available:
Description of changes:
Supports config format:
[profile default]
endpoint_url = https://global.example.com
[services s3]
endpoint_url = http://localhost:9000
Check all that applies:
Check which platforms you have built SDK on to verify the correctness of this PR.
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.