-
Notifications
You must be signed in to change notification settings - Fork 95
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
Support Dynamic Type/Attributes/Parameters #147
Comments
The design you've shown here does seem like it would neatly sidestep one of the shortcomings of the The downside of such a design is that producers and consumers of such values will presumably need to explicitly wrap and unwrap the values in the "dynamic" container, which is less convenient but more explicit than just being given a value and inspecting it directly to find out what type it has. Overall I think your approach here is a net win in that the explicitness resolves an ambiguity in the |
I’m interested to utilise dynamic types for an internal provider we have. If I try to create a custom type using dynamic pseudo type at the moment however, the runtime plan fails as it states types don’t match. Is there additional inner workings that need to be updated to support dynamic pseudo type constraint? |
There very well may be assumptions that don't hold up in the face of DPT that we'll need to fix. We haven't exercised that code path yet. If you post your code and the error you're getting, we may be able to tell you more. |
Sure I’ll get a concise example together but it’s mostly based on the above proposal. |
I have some error & workaround to share. The error message looks like this: !!!!!!!!!!!!!!!!!!!!!!!!!!! TERRAFORM CRASH !!!!!!!!!!!!!!!!!!!!!!!!!!!!
Terraform crashed! This is always indicative of a bug within Terraform.
Please report the crash with Terraform[1] so that we can fix this.
When reporting bugs, please include your terraform version, the stack trace
shown below, and any additional information which may help replicate the issue.
[1]: https://github.com/hashicorp/terraform/issues
!!!!!!!!!!!!!!!!!!!!!!!!!!! TERRAFORM CRASH !!!!!!!!!!!!!!!!!!!!!!!!!!!!
inconsistent list element types (cty.Object(map[string]cty.Type{"args":cty.List(cty.String), "command":cty.List(cty.String), "env":cty.List(cty.Object(map[string]cty.Type{"name":cty.String, "value":cty.String, "value_from":cty.Object(map[string]cty.Type{"config_map_key_ref":cty.Object(map[string]cty.Type{"key":cty.String, "name":cty.String, "optional":cty.Bool}), "field_ref":cty.Object(map[string]cty.Type{"api_version":cty.String, "field_path":cty.String}), "resource_field_ref":cty.Object(map[string]cty.Type{"container_name":cty.String, "divisor":cty.String, "resource":cty.String}), "secret_key_ref":cty.Object(map[string]cty.Type{"key":cty.String, "name":cty.String, "optional":cty.Bool})})})), "env_from":cty.List(cty.Object(map[string]cty.Type{"config_map_ref":cty.Object(map[string]cty.Type{"name":cty.String, "optional":cty.Bool}), "prefix":cty.String, "secret_ref":cty.Object(map[string]cty.Type{"name":cty.String, "optional":cty.Bool})})), "image":cty.String, "image_pull_policy":cty.String, "lifecycle":cty.Object(map[string]cty.Type{"post_start":cty.Object(map[string]cty.Type{"exec":cty.Object(map[string]cty.Type{"command":cty.List(cty.String)}), "http_get":cty.Object(map[string]cty.Type{"host":cty.String, "http_headers":cty.List(cty.Object(map[string]cty.Type{"name":cty.String, "value":cty.String})), "path":cty.String, "port":cty.DynamicPseudoType, "scheme":cty.String}), "tcp_socket":cty.Object(map[string]cty.Type{"host":cty.String, "port":cty.DynamicPseudoType})}), "pre_stop":cty.Object(map[string]cty.Type{"exec":cty.Object(map[string]cty.Type{"command":cty.List(cty.String)}), "http_get":cty.Object(map[string]cty.Type{"host":cty.String, "http_headers":cty.List(cty.Object(map[string]cty.Type{"name":cty.String, "value":cty.String})), "path":cty.String, "port":cty.DynamicPseudoType, "scheme":cty.String}), "tcp_socket":cty.Object(map[string]cty.Type{"host":cty.String, "port":cty.DynamicPseudoType})})}), "liveness_probe":cty.Object(map[string]cty.Type{"exec":cty.Object(map[string]cty.Type{"command":cty.List(cty.String)}), "failure_threshold":cty.Number, "grpc":cty.Object(map[string]cty.Type{"port":cty.Number, "service":cty.String}), "http_get":cty.Object(map[string]cty.Type{"host":cty.String, "http_headers":cty.List(cty.Object(map[string]cty.Type{"name":cty.String, "value":cty.String})), "path":cty.String, "port":cty.Number, "scheme":cty.String}), "initial_delay_seconds":cty.Number, "period_seconds":cty.Number, "success_threshold":cty.Number, "tcp_socket":cty.Object(map[string]cty.Type{"host":cty.String, "port":cty.DynamicPseudoType}), "termination_grace_period_seconds":cty.Number, "timeout_seconds":cty.Number}), "name":cty.String, "ports":cty.List(cty.Object(map[string]cty.Type{"container_port":cty.Number, "host_ip":cty.String, "host_port":cty.Number, "name":cty.String, "protocol":cty.String})), "readiness_probe":cty.Object(map[string]cty.Type{"exec":cty.Object(map[string]cty.Type{"command":cty.List(cty.String)}), "failure_threshold":cty.Number, "grpc":cty.Object(map[string]cty.Type{"port":cty.Number, "service":cty.String}), "http_get":cty.Object(map[string]cty.Type{"host":cty.String, "http_headers":cty.List(cty.Object(map[string]cty.Type{"name":cty.String, "value":cty.String})), "path":cty.String, "port":cty.Number, "scheme":cty.String}), "initial_delay_seconds":cty.Number, "period_seconds":cty.Number, "success_threshold":cty.Number, "tcp_socket":cty.Object(map[string]cty.Type{"host":cty.String, "port":cty.DynamicPseudoType}), "termination_grace_period_seconds":cty.Number, "timeout_seconds":cty.Number}), "resources":cty.Object(map[string]cty.Type{"limits":cty.Map(cty.String), "requests":cty.Map(cty.String)}), "security_context":cty.Object(map[string]cty.Type{"allow_privilege_escalation":cty.Bool, "capabilities":cty.Object(map[string]cty.Type{"add":cty.List(cty.String), "drop":cty.List(cty.String)}), "privileged":cty.Bool, "proc_mount":cty.String, "read_only_root_filesystem":cty.Bool, "run_as_group":cty.Number, "run_as_non_root":cty.Bool, "run_as_user":cty.Number, "se_linux_options":cty.Object(map[string]cty.Type{"level":cty.String, "role":cty.String, "type":cty.String, "user":cty.String}), "seccomp_profile":cty.Object(map[string]cty.Type{"localhost_profile":cty.String, "type":cty.String}), "windows_options":cty.Object(map[string]cty.Type{"gmsa_credential_spec":cty.String, "gmsa_credential_spec_name":cty.String, "host_process":cty.Bool, "run_as_user_name":cty.String})}), "startup_probe":cty.Object(map[string]cty.Type{"exec":cty.Object(map[string]cty.Type{"command":cty.List(cty.String)}), "failure_threshold":cty.Number, "grpc":cty.Object(map[string]cty.Type{"port":cty.Number, "service":cty.String}), "http_get":cty.Object(map[string]cty.Type{"host":cty.String, "http_headers":cty.List(cty.Object(map[string]cty.Type{"name":cty.String, "value":cty.String})), "path":cty.String, "port":cty.DynamicPseudoType, "scheme":cty.String}), "initial_delay_seconds":cty.Number, "period_seconds":cty.Number, "success_threshold":cty.Number, "tcp_socket":cty.Object(map[string]cty.Type{"host":cty.String, "port":cty.DynamicPseudoType}), "termination_grace_period_seconds":cty.Number, "timeout_seconds":cty.Number}), "stdin":cty.Bool, "stdin_once":cty.Bool, "termination_message_path":cty.String, "termination_message_policy":cty.String, "tty":cty.Bool, "volume_devices":cty.List(cty.Object(map[string]cty.Type{"device_path":cty.String, "name":cty.String})), "volume_mounts":cty.List(cty.Object(map[string]cty.Type{"mount_path":cty.String, "mount_propagation":cty.String, "name":cty.String, "read_only":cty.Bool, "sub_path":cty.String, "sub_path_expr":cty.String})), "working_dir":cty.String}) then cty.Object(map[string]cty.Type{"args":cty.List(cty.String), "command":cty.List(cty.String), "env":cty.List(cty.Object(map[string]cty.Type{"name":cty.String, "value":cty.String, "value_from":cty.Object(map[string]cty.Type{"config_map_key_ref":cty.Object(map[string]cty.Type{"key":cty.String, "name":cty.String, "optional":cty.Bool}), "field_ref":cty.Object(map[string]cty.Type{"api_version":cty.String, "field_path":cty.String}), "resource_field_ref":cty.Object(map[string]cty.Type{"container_name":cty.String, "divisor":cty.String, "resource":cty.String}), "secret_key_ref":cty.Object(map[string]cty.Type{"key":cty.String, "name":cty.String, "optional":cty.Bool})})})), "env_from":cty.List(cty.Object(map[string]cty.Type{"config_map_ref":cty.Object(map[string]cty.Type{"name":cty.String, "optional":cty.Bool}), "prefix":cty.String, "secret_ref":cty.Object(map[string]cty.Type{"name":cty.String, "optional":cty.Bool})})), "image":cty.String, "image_pull_policy":cty.String, "lifecycle":cty.Object(map[string]cty.Type{"post_start":cty.Object(map[string]cty.Type{"exec":cty.Object(map[string]cty.Type{"command":cty.List(cty.String)}), "http_get":cty.Object(map[string]cty.Type{"host":cty.String, "http_headers":cty.List(cty.Object(map[string]cty.Type{"name":cty.String, "value":cty.String})), "path":cty.String, "port":cty.DynamicPseudoType, "scheme":cty.String}), "tcp_socket":cty.Object(map[string]cty.Type{"host":cty.String, "port":cty.DynamicPseudoType})}), "pre_stop":cty.Object(map[string]cty.Type{"exec":cty.Object(map[string]cty.Type{"command":cty.List(cty.String)}), "http_get":cty.Object(map[string]cty.Type{"host":cty.String, "http_headers":cty.List(cty.Object(map[string]cty.Type{"name":cty.String, "value":cty.String})), "path":cty.String, "port":cty.DynamicPseudoType, "scheme":cty.String}), "tcp_socket":cty.Object(map[string]cty.Type{"host":cty.String, "port":cty.DynamicPseudoType})})}), "liveness_probe":cty.Object(map[string]cty.Type{"exec":cty.Object(map[string]cty.Type{"command":cty.List(cty.String)}), "failure_threshold":cty.Number, "grpc":cty.Object(map[string]cty.Type{"port":cty.Number, "service":cty.String}), "http_get":cty.Object(map[string]cty.Type{"host":cty.String, "http_headers":cty.List(cty.Object(map[string]cty.Type{"name":cty.String, "value":cty.String})), "path":cty.String, "port":cty.DynamicPseudoType, "scheme":cty.String}), "initial_delay_seconds":cty.Number, "period_seconds":cty.Number, "success_threshold":cty.Number, "tcp_socket":cty.Object(map[string]cty.Type{"host":cty.String, "port":cty.DynamicPseudoType}), "termination_grace_period_seconds":cty.Number, "timeout_seconds":cty.Number}), "name":cty.String, "ports":cty.List(cty.Object(map[string]cty.Type{"container_port":cty.Number, "host_ip":cty.String, "host_port":cty.Number, "name":cty.String, "protocol":cty.String})), "readiness_probe":cty.Object(map[string]cty.Type{"exec":cty.Object(map[string]cty.Type{"command":cty.List(cty.String)}), "failure_threshold":cty.Number, "grpc":cty.Object(map[string]cty.Type{"port":cty.Number, "service":cty.String}), "http_get":cty.Object(map[string]cty.Type{"host":cty.String, "http_headers":cty.List(cty.Object(map[string]cty.Type{"name":cty.String, "value":cty.String})), "path":cty.String, "port":cty.Number, "scheme":cty.String}), "initial_delay_seconds":cty.Number, "period_seconds":cty.Number, "success_threshold":cty.Number, "tcp_socket":cty.Object(map[string]cty.Type{"host":cty.String, "port":cty.DynamicPseudoType}), "termination_grace_period_seconds":cty.Number, "timeout_seconds":cty.Number}), "resources":cty.Object(map[string]cty.Type{"limits":cty.Map(cty.String), "requests":cty.Map(cty.String)}), "security_context":cty.Object(map[string]cty.Type{"allow_privilege_escalation":cty.Bool, "capabilities":cty.Object(map[string]cty.Type{"add":cty.List(cty.String), "drop":cty.List(cty.String)}), "privileged":cty.Bool, "proc_mount":cty.String, "read_only_root_filesystem":cty.Bool, "run_as_group":cty.Number, "run_as_non_root":cty.Bool, "run_as_user":cty.Number, "se_linux_options":cty.Object(map[string]cty.Type{"level":cty.String, "role":cty.String, "type":cty.String, "user":cty.String}), "seccomp_profile":cty.Object(map[string]cty.Type{"localhost_profile":cty.String, "type":cty.String}), "windows_options":cty.Object(map[string]cty.Type{"gmsa_credential_spec":cty.String, "gmsa_credential_spec_name":cty.String, "host_process":cty.Bool, "run_as_user_name":cty.String})}), "startup_probe":cty.Object(map[string]cty.Type{"exec":cty.Object(map[string]cty.Type{"command":cty.List(cty.String)}), "failure_threshold":cty.Number, "grpc":cty.Object(map[string]cty.Type{"port":cty.Number, "service":cty.String}), "http_get":cty.Object(map[string]cty.Type{"host":cty.String, "http_headers":cty.List(cty.Object(map[string]cty.Type{"name":cty.String, "value":cty.String})), "path":cty.String, "port":cty.DynamicPseudoType, "scheme":cty.String}), "initial_delay_seconds":cty.Number, "period_seconds":cty.Number, "success_threshold":cty.Number, "tcp_socket":cty.Object(map[string]cty.Type{"host":cty.String, "port":cty.DynamicPseudoType}), "termination_grace_period_seconds":cty.Number, "timeout_seconds":cty.Number}), "stdin":cty.Bool, "stdin_once":cty.Bool, "termination_message_path":cty.String, "termination_message_policy":cty.String, "tty":cty.Bool, "volume_devices":cty.List(cty.Object(map[string]cty.Type{"device_path":cty.String, "name":cty.String})), "volume_mounts":cty.List(cty.Object(map[string]cty.Type{"mount_path":cty.String, "mount_propagation":cty.String, "name":cty.String, "read_only":cty.Bool, "sub_path":cty.String, "sub_path_expr":cty.String})), "working_dir":cty.String}))
goroutine 74 [running]:
runtime/debug.Stack()
/usr/local/go/src/runtime/debug/stack.go:24 +0x65
runtime/debug.PrintStack()
/usr/local/go/src/runtime/debug/stack.go:16 +0x19
github.com/hashicorp/terraform/internal/logging.PanicHandler()
/go/pkg/mod/github.com/hashicorp/[email protected]/internal/logging/panic.go:55 +0x153
panic({0x21e7200, 0xc003e71bd0})
/usr/local/go/src/runtime/panic.go:890 +0x262
github.com/zclconf/go-cty/cty.ListVal({0xc0086e4700, 0x2, 0xc0036d8c80?})
/go/pkg/mod/github.com/zclconf/[email protected]/cty/value_init.go:166 +0x42e
github.com/zclconf/go-cty/cty/msgpack.unmarshalList(0x2b6f590?, {{0x2b6f600?, 0xc0036d8c80?}}, {0xc0086e46c0?, 0x4, 0x4})
/go/pkg/mod/github.com/zclconf/[email protected]/cty/msgpack/unmarshal.go:161 +0x4bc
github.com/zclconf/go-cty/cty/msgpack.unmarshal(0x221ec00?, {{0x2b6f590?, 0xc0036d8c90?}}, {0xc0086e46c0?, 0x4, 0x4})
/go/pkg/mod/github.com/zclconf/[email protected]/cty/msgpack/unmarshal.go:52 +0x41a
github.com/zclconf/go-cty/cty/msgpack.unmarshalObject(0xc0062f7f88?, 0xc0064355c0, {0xc0086e46c0?, 0x3, 0x4})
/go/pkg/mod/github.com/zclconf/[email protected]/cty/msgpack/unmarshal.go:297 +0x4b6
github.com/zclconf/go-cty/cty/msgpack.unmarshal(0x221ec00?, {{0x2b6f600?, 0xc0036d9c60?}}, {0xc0086e46c0?, 0x3, 0x4})
/go/pkg/mod/github.com/zclconf/[email protected]/cty/msgpack/unmarshal.go:60 +0x555
github.com/zclconf/go-cty/cty/msgpack.unmarshalObject(0xc0062f7f88?, 0xc0064355f0, {0xc000627e80?, 0x2, 0x2})
/go/pkg/mod/github.com/zclconf/[email protected]/cty/msgpack/unmarshal.go:297 +0x4b6
github.com/zclconf/go-cty/cty/msgpack.unmarshal(0x221ec00?, {{0x2b6f600?, 0xc0036d9c70?}}, {0xc000627e80?, 0x2, 0x2})
/go/pkg/mod/github.com/zclconf/[email protected]/cty/msgpack/unmarshal.go:60 +0x555
github.com/zclconf/go-cty/cty/msgpack.unmarshalObject(0xc0062f7f88?, 0xc006435650, {0xc0036d9ca0?, 0x1, 0x1})
/go/pkg/mod/github.com/zclconf/[email protected]/cty/msgpack/unmarshal.go:297 +0x4b6
github.com/zclconf/go-cty/cty/msgpack.unmarshal(0x221ec00?, {{0x2b6f600?, 0xc0036d9c80?}}, {0xc0036d9ca0?, 0x1, 0x1})
/go/pkg/mod/github.com/zclconf/[email protected]/cty/msgpack/unmarshal.go:60 +0x555
github.com/zclconf/go-cty/cty/msgpack.unmarshalObject(0xc0062f7f88?, 0xc0064356b0, {0x0?, 0x0, 0x0})
/go/pkg/mod/github.com/zclconf/[email protected]/cty/msgpack/unmarshal.go:297 +0x4b6
github.com/zclconf/go-cty/cty/msgpack.unmarshal(0xc0062f7f88?, {{0x2b6f600?, 0xc0036d9c90?}}, {0x0?, 0x0, 0x0})
/go/pkg/mod/github.com/zclconf/[email protected]/cty/msgpack/unmarshal.go:60 +0x555
github.com/zclconf/go-cty/cty/msgpack.Unmarshal({0xc003e33300, 0x12fa, 0x1300}, {{0x2b6f600?, 0xc0036d9c90?}})
/go/pkg/mod/github.com/zclconf/[email protected]/cty/msgpack/unmarshal.go:22 +0x105
github.com/hashicorp/terraform/internal/plugin6.decodeDynamicValue(0x0?, {{0x2b6f600?, 0xc0036d9c90?}})
/go/pkg/mod/github.com/hashicorp/[email protected]/internal/plugin6/grpc_provider.go:688 +0x97
github.com/hashicorp/terraform/internal/plugin6.(*GRPCProvider).PlanResourceChange(_, {{0xc000056db0, 0x18}, {{{0x2b6f600, 0xc007dd2380}}, {0x0, 0x0}}, {{{0x2b6f600, 0xc00893fa10}}, {0x221f740, ...}}, ...})
/go/pkg/mod/github.com/hashicorp/[email protected]/internal/plugin6/grpc_provider.go:466 +0x859
github.com/hashicorp/terraform/internal/terraform.(*NodeAbstractResourceInstance).plan(0xc004c683c0, {0x2b85ad8, 0xc004754380}, 0x0, 0x0, 0x0, {0x0, 0x0, 0x0?})
/go/pkg/mod/github.com/hashicorp/[email protected]/internal/terraform/node_resource_abstract_instance.go:802 +0x12a3
github.com/hashicorp/terraform/internal/terraform.(*NodePlannableResourceInstance).managedResourceExecute(0xc0089de080, {0x2b85ad8, 0xc004754380})
/go/pkg/mod/github.com/hashicorp/[email protected]/internal/terraform/node_resource_plan_instance.go:218 +0xd6e
github.com/hashicorp/terraform/internal/terraform.(*NodePlannableResourceInstance).Execute(0x0?, {0x2b85ad8?, 0xc004754380?}, 0x0?)
/go/pkg/mod/github.com/hashicorp/[email protected]/internal/terraform/node_resource_plan_instance.go:60 +0x90
github.com/hashicorp/terraform/internal/terraform.(*ContextGraphWalker).Execute(0xc004c660f0, {0x2b85ad8, 0xc004754380}, {0x7f08101c3640, 0xc0089de080})
/go/pkg/mod/github.com/hashicorp/[email protected]/internal/terraform/graph_walk_context.go:136 +0xc2
github.com/hashicorp/terraform/internal/terraform.(*Graph).walk.func1({0x25706a0, 0xc0089de080})
/go/pkg/mod/github.com/hashicorp/[email protected]/internal/terraform/graph.go:75 +0x315
github.com/hashicorp/terraform/internal/dag.(*Walker).walkVertex(0xc0089e0180, {0x25706a0, 0xc0089de080}, 0xc0089de1c0)
/go/pkg/mod/github.com/hashicorp/[email protected]/internal/dag/walk.go:381 +0x2f6
created by github.com/hashicorp/terraform/internal/dag.(*Walker).Update
/go/pkg/mod/github.com/hashicorp/[email protected]/internal/dag/walk.go:304 +0xf65} This is happening because of the following example terraform config (simplified): resource "example_resource" "testcase" {
list_of_objects = [
{
name = "first"
dynamic_attribute = 123
},
{
name = "second"
},
]
}
I think the fundamental problem here is that |
Thanks for sharing that, @sebhoss! I expect there is an improvement to make to the framework to avoid a value like this getting so far through before it is detected, but what you showed here also indicates a bug in Terraform Core: it seems to be possible for a provider to crash Terraform Core by returning a value that doesn't conform to the schema, whereas that's supposed to be handled as a proper error message so that Terraform Core will at least get a chance to exit cleanly and tidy up any other concurrent operations in progress. Would you mind reporting this in the |
Please note that the framework does not officially support |
@apparentlymart ok created hashicorp/terraform#32092 for that @bflad yeah I understand. I was aware of this ticket here before deciding to give it a try and was actually surprised how well it all went. In most cases it just works(tm) and I only shared the log output as input for future design work in case you guys ever decide to implement a dynamic type. If there is anything I can do to help or try out, please let me know! |
@bflad thank you for pointing me to this issue. Just trying to catch up here, it looks like using |
…hashicorp#147) * Bump github.com/hashicorp/terraform-plugin-docs from 0.14.1 to 0.15.0 Bumps [github.com/hashicorp/terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs) from 0.14.1 to 0.15.0. - [Release notes](https://github.com/hashicorp/terraform-plugin-docs/releases) - [Changelog](https://github.com/hashicorp/terraform-plugin-docs/blob/main/CHANGELOG.md) - [Commits](hashicorp/terraform-plugin-docs@v0.14.1...v0.15.0) --- updated-dependencies: - dependency-name: github.com/hashicorp/terraform-plugin-docs dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> * Regenerate documentation using updated tfplugindocs --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Brian Flad <[email protected]>
Please note that we will also use this issue as a catching point for dynamic function parameter support. This functionality is being actively considered for implementation in the coming weeks (but not fully committed yet). |
If you've been following along in this issue, Dynamic type support has just landed in We have written some initial documentation to capture some of the scenarios you'll need to account for when using a dynamic type: https://developer.hashicorp.com/terraform/plugin/framework/handling-data/dynamic-data (may need to let our CDN catch up, since it's just been released). As always, if you run into any problems, please submit a new issue! |
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. |
Module version
Use-cases
There are sometimes occasions in which provider developers want to use unstructured output or input. See, for example, the
kubernetes_manifest
implementation, or thetfe_outputs
data source. See also hashicorp/terraform-provider-external#76. Allowing people to do this from the framework offers a friendlier interface for this functionality than plugin-go.Attempted Solutions
Traditionally, this has been achieved through muxing in plugin-go.
Proposal
If we add a
types.DynamicType
andtypes.Dynamic
implementation, we can natively support this:The text was updated successfully, but these errors were encountered: