From 737ff99157512f7a0fb4429f4f403bd21402b179 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Mon, 26 Apr 2021 09:22:09 -0400 Subject: [PATCH] bug: Fix `linode-cli linodes create` operation In testing an unrelated CLI change, I noticed this: ```bash $ linode-cli linodes create --help linode-cli linodes create Linode Create Arguments: --root_pass: This will set the root user's password on the newly-created Linode. --stackscript_id: A StackScript ID that will cause the referenced StackScript to be run duringdeployment of this Linode. --authorized_keys: A list of public SSH keys that will be automatically appendedto the root user's `~/. --authorized_users: A list of usernames. --stackscript_data: This field is required only if the StackScript being deployed requires inputdata from the User for successful completion. --booted: This field defaults to `true` if the Linode is created with an Image or from a Backup. --image: An Image ID to deploy the Disk from. ``` That's not good - the `linodes create` operation is missing many parameters, including `type` and `region` that are required. After some digging, I determined that it was because the `allOf` in `/linodes/instances.post.requestBody.content.application/json.schema` section was not nested properly; the schema should be all of the references `LinodeRequest` _and_ the given properties. Having an `allOf` alongside `properties` isn't really correct (although it's apparently not invalid). Built off this spec, the CLI now see the full request: ```bash $ python -m linodecli linodes create --help linode-cli linodes create Linode Create Arguments: --region: (required) The [Region](/docs/api/regions/#regions-list) where the Linode will be located. --type: (required) The [Linode Type](/docs/api/linode-types/#types-list) of the Linode you are creating. --interfaces.label: The name of this interface. --root_pass: This will set the root user's password on the newly-created Linode. --backup_id: A Backup ID from another Linode's available backups. --group: A deprecated property denoting a group label for this Linode. --stackscript_id: A StackScript ID that will cause the referenced StackScript to be run duringdeployment of this Linode. --authorized_keys: A list of public SSH keys that will be automatically appendedto the root user's `~/. --stackscript_data: This field is required only if the StackScript being deployed requires inputdata from the User for successful completion. --image: An Image ID to deploy the Disk from. --tags: An array of tags applied to this object. --backups_enabled: If this field is set to `true`, the created Linode will automatically beenrolled in the Linode Backup service. --label: The Linode's label is for display purposes only. --interfaces.purpose: The type of interface. --private_ip: If true, the created Linode will have private networking enabled and assigned a private IPv4 address. --swap_size: When deploying from an Image, this field is optional, otherwise it is ignored. --interfaces.ipam_address: This Network Interface's private IP address in Classless Inter-Domain Routing (CIDR) notation. --authorized_users: A list of usernames. --booted: This field defaults to `true` if the Linode is created with an Image or from a Backup. ``` I could be persuaded that the CLI's spec parser is incorrectly merging the `allOf` with the same-level `properties`, but I do not believe this is the case. The OpenAPI Specification is light on details here, but all examples using `allOf` do not include sibling nodes like this. --- openapi.yaml | 112 +++++++++++++++++++++++++-------------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/openapi.yaml b/openapi.yaml index 34c5d8e54..2a3a35172 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -3792,62 +3792,62 @@ paths: type: object allOf: - $ref: '#/components/schemas/LinodeRequest' - properties: - backup_id: - type: integer - example: 1234 - description: | - A Backup ID from another Linode's available backups. Your User must have - `read_write` access to that Linode, the Backup must have a `status` of - `successful`, and the Linode must be deployed to the same `region` as the Backup. - See [/linode/instances/{linodeId}/backups](/docs/api/linode-instances/#backups-list) - for a Linode's available backups. - - This field and the `image` field are mutually exclusive. - backups_enabled: - type: boolean - description: | - If this field is set to `true`, the created Linode will automatically be - enrolled in the Linode Backup service. This will incur an additional charge. - The cost for the Backup service is dependent on the Type of Linode deployed. - - This option is always treated as `true` if the account-wide `backups_enabled` - setting is `true`. See [account settings](/docs/api/account/#account-settings-view) - for more information. - - Backup pricing is included in the response from [/linodes/types](/docs/api/linode-types/#types-list) - swap_size: - type: integer - example: 512 - description: > - When deploying from an Image, this field is optional, otherwise it is ignored. - This is used to set the swap disk size for the newly-created Linode. - default: 512 - type: - type: string - description: > - The [Linode Type](/docs/api/linode-types/#types-list) of the Linode - you are creating. - example: g6-standard-2 - region: - type: string - description: > - The [Region](/docs/api/regions/#regions-list) where the Linode - will be located. - example: us-east - label: - $ref: '#/components/schemas/Linode/properties/label' - tags: - $ref: '#/components/schemas/Linode/properties/tags' - group: - $ref: '#/components/schemas/Linode/properties/group' - private_ip: - type: boolean - description: > - If true, the created Linode will have private networking enabled and assigned a private IPv4 address. - example: true - interfaces: - $ref: '#/components/schemas/LinodeConfigInterfaces' + - properties: + backup_id: + type: integer + example: 1234 + description: | + A Backup ID from another Linode's available backups. Your User must have + `read_write` access to that Linode, the Backup must have a `status` of + `successful`, and the Linode must be deployed to the same `region` as the Backup. + See [/linode/instances/{linodeId}/backups](/docs/api/linode-instances/#backups-list) + for a Linode's available backups. + + This field and the `image` field are mutually exclusive. + backups_enabled: + type: boolean + description: | + If this field is set to `true`, the created Linode will automatically be + enrolled in the Linode Backup service. This will incur an additional charge. + The cost for the Backup service is dependent on the Type of Linode deployed. + + This option is always treated as `true` if the account-wide `backups_enabled` + setting is `true`. See [account settings](/docs/api/account/#account-settings-view) + for more information. + + Backup pricing is included in the response from [/linodes/types](/docs/api/linode-types/#types-list) + swap_size: + type: integer + example: 512 + description: > + When deploying from an Image, this field is optional, otherwise it is ignored. + This is used to set the swap disk size for the newly-created Linode. + default: 512 + type: + type: string + description: > + The [Linode Type](/docs/api/linode-types/#types-list) of the Linode + you are creating. + example: g6-standard-2 + region: + type: string + description: > + The [Region](/docs/api/regions/#regions-list) where the Linode + will be located. + example: us-east + label: + $ref: '#/components/schemas/Linode/properties/label' + tags: + $ref: '#/components/schemas/Linode/properties/tags' + group: + $ref: '#/components/schemas/Linode/properties/group' + private_ip: + type: boolean + description: > + If true, the created Linode will have private networking enabled and assigned a private IPv4 address. + example: true + interfaces: + $ref: '#/components/schemas/LinodeConfigInterfaces' responses: '200': description: >