Crates.io | eio-okta-data |
lib.rs | eio-okta-data |
version | |
source | src |
created_at | 2024-12-11 06:15:25.327934 |
updated_at | 2024-12-11 06:15:25.327934 |
description | Data Types for Okta |
homepage | https://github.com/rancher-eio/okta-sync |
repository | https://github.com/rancher-eio/okta-sync |
max_upload_size | |
id | 1479609 |
Cargo.toml error: | TOML parse error at line 19, column 1 | 19 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include` |
size | 0 |
This crate contains data types only.
In the details below, the following conventions are assumed:
{Type}
is intended as the type identifier of some type.
{Type}Status
should be understood as FooStatus
in relation to type Foo
, and BarStatus
in relation to type Bar
.{field}
is intended as the named identifier of a struct field.
fn set_{field}(&mut self, value: T)
should be understood as fn set_foo(&mut self)
in relation to a field named foo
with type T
on some struct. It's probably fair to assume that such a function sets the foo
field to whatever value
was given.(...)
is intended to be understood as "a tuple with some number of members", the number likely being fixed, but unspecified in the example.prelude
module at the root of the crate.As a loose guideline, most features are named for the crate it adds integrations for, or the attribute it adds to a type.
arbitrary
arbitrary::Arbitrary
for all types, to support fuzzing tools like cargo-fuzz
and AFL
.builder
{Type}Builder
struct alongside all struct types.
Into
for the corresponding field type.{Type}BuilderError
struct.clap
clap::Args
for all struct types, allowing fields to be read from CLI options/flags.clap::ValueEnum
for all enum types, allowing use and validation as CLI args.comparable
{Type}Change
enum alongside all struct types.{Type}Desc
struct alongside all struct types.comparable::Comparable
for all types.
fn comparison(&self, other: &Self) -> Vec<{Type}Change>
function to all types.dissolve
fn dissolve(self) -> (...)
method to all struct types.
remain
.dummy
fake::Dummy
for all types, allowing generation of plausible examples.getter
fn {{field}}(&self) -> &T
method for each field of all struct types.
Copy
types, this returns a copy of the data instead.proptest
proptest::Arbitrary
for all types, which in turn enables property-based testing with automatic shrinking.schemars
schamars::JsonSchema
for all types
kube
to generate Kubernetes Controllers and such from these types.serde
serde::Serialize
and serde::Deserialize
for all types.
patch
{Type}Patch
struct alongside all struct types.
{Type}
, with the notable difference that all fields are optional.Default
, even if {Type}
doesn't (default being an empty patch).struct_patch::Patch
for all struct types.
serde
feature is enabled, {Type}Patch
is (de)serializable.comparable
feature is enabled, {Type}Patch
implements comparable::Comparable
.builder
feature is enabled, adds a {Type}PatchBuilder
struct.strum
derive
-able traits from the strum
crate for all enum types.validate
validator::Validate
for all struct types.validator::Validate
for all enum types.
Ok(())
for enum variants that do not contain data.
.validate()
on the data and returns the result.arbitrary
, fake
, and proptest
have some overlap, in that they all allow generation of arbitrary samples for supported types. Where they differ is the primary use case.
fake::Dummy
is intended to generate human-friendly samples for the purpose of testing, documentation, mocking, and prototyping applications. Additional effort has been made to have these generators produce plausible examples. For example, a postal address generated here is likely to resemble a realistic address, even if the address doesn't exist, it should be something that looks like it could. They allow you to build using realistic data without requiring access to any service. As such, they are often useful for unit testing, but less so for integration testing.
proptest::Arbitrary
is intended to be driven via cargo test
, generating hundreds (or thousands) of randomized inputs for each test, and when things fail, retrying with progressively simpler variants of the failing input until it isolates a minimal reproducible failure, and then producing a comittable regression file to ensure that failure is always tested going forward.
arbitrary::Arbitrary
however, is intended to be driven with cargo fuzz
, potentially generating an exhaustive set of all possible inputs (given infinite time). The purpose here is using input fuzzing to guide automated exploration and analysis of potential execution paths in the program.
comparable
and struct_patch
also have some overlapping functionality, but the intended use is considerably different.
comparable::Comparable
is intended for diagnostics, testing, and verification. It produces granular, iterable changesets with human-friendly descriptions of those changes, making it straightforward to identify small changes in deeply nested structures. {Type}Change
and {Type}Desc
ensure that there is a representation for all possible changes that could occur to a given data type. The comparable
crate also provides a powerful assert_changes!
macro that uses these to define test expectations, and is very useful when testing mutable operations.
struct_patch::Patch
on the other hand, is intended to be used for transforming data. {Type}Patch
can be used to apply partial changes to the original type (for example, redacting sensitive information). These patches can be added together and/or merged, allowing complex patching processes to be composed from simple, testable fragments. It is also possible to take any two instances of a patchable data type and produce a strongly-typed patch that transforms one into the other. This in turn provides the core functionality for staging and undoing changes.
If the patch
feature is enabled, the {Type}Patch
struct may feel slightly counterintuitive, when {Type}
has fields that are Option<T>
.
use okta_data::v2024_07_0::management::components::schemas::{
user_profile::{UserProfilePatch, UserProfilePatchBuilder},
};
let patch = UserProfilePatchBuilder::default()
.employee_number(Some(Some(String::from("31337"))))
.build().unwrap();
The Option<Option<T>>
there is the part that feels a bit weird, right? The reason it works this way is because we need to distinguish between "this patch does not apply to this field" (None
), and "this patch applies to this field, and is explicitly setting it to None
(which we represent as Some(None)
). As a result, setting it to a specific value Some(Some(value))
, which is visually unappealing, but logically coherent.
Some fields like User::embedded
do not have a fixed definition in the Okta Managment API OpenAPI Specification, and so are represented as serde_json::Value
, so you can define your own conversions for whatever sort of data you happen to put in there.
However, given that these fields are unspecified, they're also untestable within the scope of this crate. As such, several features (notably testing-oriented ones such as comparable
, proptest
, dummy
, and arbitrary
) simply ignore these fields.