oxidecomputer / progenitor

An OpenAPI client generator
512 stars 63 forks source link

PagerDuty REST Api generation fails #591

Open nikolay-te opened 1 year ago

nikolay-te commented 1 year ago

I'm trying to use progenitor to generate a PagerDuty API client using their published OpenAPI v3 spec from here openapiv3.json

I have these dependencies in my Cargo.toml:

[dependencies]
futures = "0.3"
progenitor = { version = "0.4" }
reqwest = { version = "0.11", features = ["json", "stream"] }
serde = { version = "1.0", features = ["derive"] }
chrono = { version = "0.4", features = ["serde"] }
uuid = { version = "1.0.0", features = ["serde", "v4"] }
base64 = "0.21"
rand = "0.8"
regress = "0.7"

And a simple lib.rs:

use progenitor::generate_api;

generate_api!("spec/openapiv3.json");

However when running cargo build I get this error:

error: proc macro panicked
 --> pagerduty/src/lib.rs:3:1
  |
3 | generate_api!("spec/openapiv3.json");
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = help: message: not clear what we could usefully do here Schema {
              schema_data: SchemaData {
                  nullable: false,
                  read_only: false,
                  write_only: false,
                  deprecated: false,
                  external_docs: None,
                  example: None,
                  title: None,
                  description: None,
                  discriminator: None,
                  default: None,
                  extensions: {},
              },
              schema_kind: Any(
                  AnySchema {
                      typ: None,
                      pattern: None,
                      multiple_of: None,
                      exclusive_minimum: None,
                      exclusive_maximum: None,
                      minimum: None,
                      maximum: None,
                      properties: {},
                      required: [],
                      additional_properties: None,
                      min_properties: None,
                      max_properties: None,
                      items: None,
                      min_items: None,
                      max_items: None,
                      unique_items: None,
                      enumeration: [
                          String("event_orchestration_reference"),
                      ],
                      format: None,
                      min_length: None,
                      max_length: None,
                      one_of: [],
                      all_of: [],
                      any_of: [],
                      not: None,
                  },
              ),
          }

error: could not compile `pagerduty` (lib) due to previous error
ahl commented 1 year ago

Thanks for filing this. An easy bug and a harder bug here. The easy bug is that progenitor, amazingly, doesn't handle the schema { "enum": ["event_orchestration_reference"] }. This is in some ancient (2 years old) code that doesn't handle a variety of conversions.

Once I fixed that, I found the second problem: there are a bunch of what I'll call "unexpected" references. Here are some notable examples:

"$ref": "#/components/schemas/OrchestrationGlobal/allOf/1/properties/orchestration_path/properties/catch_all/properties/actions/allOf/1"
"$ref": "#/components/responses/Conflict/content/application~1json/schema"

Most OpenAPI documents limit this references to paths of the form: "#/components/X/Y". I've seen some examples of additional nesting (e.g. https://github.com/oxidecomputer/typify/issues/392), but not where we're descending into an allOf for example to pluck out a particularly useful schema. It's kind of weird.

My first suggestion is to pre-process the file to either inline these weird references (taking care not to fall into a cycle) or pull them out as top-level components/schemas. I can imagine how progenitor / typify might handle this itself; but I'm not sure yet of the complexity of it.


Note to self: https://swagger.io/docs/specification/using-ref/ explains the ~1 escape syntax in refs.

nikolay-te commented 1 year ago

Thanks for looking into this! I'll see if I can come up with something to pre-process the schema and give it a go again once #592 is merged.

nikolay-te commented 6 months ago

Just tried re-running this with the latest git code and 0.6.0 returning now only this error:

error: proc macro panicked
 --> pagerduty/src/lib.rs:3:1
  |
3 | generate_api!("spec/openapiv3.json");
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = help: message: $ref #/components/parameters/audit_method_type/schema is missing

error: could not compile `pagerduty` (lib) due to 1 previous error

But I see it in the json file:

cat spec/openapiv3.json| jq .components.parameters.audit_method_type.schema
{
  "type": "string",
  "description": "Describes the method used to perform the action:\n\n`browser` -- authenticated user session. Session value is not returned in the `truncated_token` field.\n\n`oauth` -- access token obtained via the OAuth flow. Truncated token value is returned in the `truncated_token` field.\n\n`api_token` -- Pagerduty API token. Truncated token value is returned in the `truncated_token` field.\n\n`identity_provider` -- action performed by an Identity provider on behalf of a user. No value is returned in the `truncated_token` field.\n\n`other` -- Method that does not fall in the predefined categories. Truncated token value MAY be returned in the `truncated_token` field.\n",
  "enum": [
    "browser",
    "oauth",
    "api_token",
    "identity_provider",
    "other"
  ]
}