Resource Bodies and Connector::filter(addr)
Implementing the Resource trait defines how the connector stores resource files on-disk, for example, as RON or YAML. The body should contain user-editable state only, and not include information already carried by the address.
The S3 bucket resource is a clean example:
Notice that the bucket name and bucket region are not in the resource body. Those already live in the implementation of ResourceAddress, S3ResourceAddress, encoded as aws/s3/{region}/buckets/{name}.ron.
Resource::to_bytes() and Resource::from_bytes() should try to encode/decode the resource to/from its on-disk format. This sounds complex, but in practice it's just using Serialize/Deserialize with whatever format you want. See the GithubConnector for an example. Notice that from_bytes() also gets the address, to determine by decoding it what type to deserialize:
Connector::filter(addr): declaring the address space to the host
Connector::filter(addr) is used to inform the host of which files "belong" to the connector.
If a connector returns FilterResponse::Resource for a given address, it indicates to the host that it should exclusively use this file as the state for some particular resource at that address.
In other words, this address decoding logic is the mechanism by which connectors describe an
hierarchy of nested objects.
So, the S3Connector might return:
aws/s3/us-east-1/buckets/office.ron => FilterResponse::Resource aws/s3/eu-west-2/buckets/backup.ron => FilterResponse::Resource some_random_file.txt => FilterResponse::None aws/vpc/eu-west-2/vpcs/main.ron => FilterResponse::None
Note that addresses never include the prefix here; connectors run with their working directory
at the root of the git repo, but they are informed of their prefix at new() and should save it if they need it (for loading configs etc).
In other words, if the full path is "./${prefix}/${addr}", connectors are only passed "./${addr}" in operations like filter, get, plan, etc.
Connector-specific config is separate. If a path is a connector config, filter() should return FilterResponse::Config so upstream caches of filter() can be invalidated when it changes:
If the API you're writing a connector for already has a declarative interface of some sort, you may be able to use it as your native representation in Autoschematic. The Kubernetes connector serializes Kubernetes objects directly and stores them as .yaml files, and the Snowflake connector directly fetches and applies Snowflake's Declarative Data Language (DDL) for manangin schemas, tables, and other SQL objects. Connector ops for those connectors are
Otherwise, most connectors currently use RON, the Rusty Object Notation as their on-disk format. It's particularly well suited for modelling Rust structs & enums, and Autoschematic along with the language server and vscode extension support RON even further with syntax highlighting, autoformatting, docs-on-hover, and even syntax & type error highlighting for internal and connector-supported files.
Reference files:

