Skip to content

bug: Schema loading process crashes ungracefully with wrong schema file #464

Open
@a-delannoy

Description

@a-delannoy

Component

infrahubctl

Infrahub SDK version

1.12.1

Current Behavior

When trying to load a specific wrongly structured schema (defined in the steps to reproduce the issue), the schema loading process fails ungracefully with the following error message:

Unable to load the schema:
Error: list indices must be integers or slices, not str
Traceback (most recent call last):
  File "/Users/Antoine/projects/dogfooding/.venv/lib/python3.12/site-packages/infrahub_sdk/ctl/utils.py", line 91, in async_wrapper
    return await func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/Antoine/projects/dogfooding/.venv/lib/python3.12/site-packages/infrahub_sdk/ctl/schema.py", line 129, in load
    display_schema_load_errors(response=response.errors, schemas_data=schemas_data)
  File "/Users/Antoine/projects/dogfooding/.venv/lib/python3.12/site-packages/infrahub_sdk/ctl/schema.py", line 80, in display_schema_load_errors
    input_label = node[loc_path[6]].get("name", None)
                  ~~~~~~~~~~~~~~^^^^^^^^^^^^^
TypeError: list indices must be integers or slices, not str

Expected Behavior

According to the backend team, this error should be handled as a gracefull error handling.

Steps to Reproduce

Infrahub instance

The Infrahub instance is setup using the docker compose instantiation on the infrahub repository

The command used to run the instance is: inv demo.start

Environement variables

Only two env vars are defined:

The schema file

To load the schema, I use the following command:

infrahubctl schema load schema-library/base security-schema.yaml

Where:

  • schema-library/base is conform to this state in the schema-library repository
  • security-schema.yaml has the following content
---
version: "1.0"
generics:
  - name: Rule
    namespace: Security
    icon: mdi:security
    order_by:
      - index__value
    display_labels:
      - name__value
    uniqueness_constraints:
      - ["rule_set", "index__value"]
    attributes:
      - name: name
        kind: Text
        unique: false
      - name: index
        kind: Number
        optional: true
      - name: action
        optional: true
        kind: Dropdown
        default_value: allow
        choices:
          - label: allow
            name: allow
          - label: deny
            name: deny
    relationships:
      - name: src
        peer: SecurityIdentity
        identifier: src_rule__security_identity
        optional: false
        cardinality: many
        kind: Attribute
        direction: outbound
      - name: dst
        peer: SecurityIdentity
        identifier: dst_rule__security_identity
        optional: false
        cardinality: many
        kind: Attribute
        direction: outbound
      - name: rule_set
        peer: SecurityRuleSet
        cardinality: one
        optional: false

  - name: Identity
    namespace: Security
    icon: mdi:security
    attributes:
      - name: name
        kind: Text
        unique: true

  - name: ProtocolSpecifier
    namespace: Security
    icon: mdi:security
    display_labels:
      - name__value
    human_friendly_id:
      - name__value
    attributes:
      - name: name
        kind: Text
        unique: true

  - name: DeviceGroupOwner
    namespace: Security
    icon: mdi:account-group
    display_labels:
      - name__value
    attributes:
      - name: name
        kind: Text
        unique: true
    relationships:
      - name: device_groups
        peer: SecurityDeviceGroup
        optional: true
        cardinality: many
        kind: Attribute

nodes:
  - name: TailscaleAutogroup
    namespace: Security
    icon: mdi:zip-box
    inherit_from: ["SecurityIdentity"]
    display_labels:
      - name__value
    attributes:
      - name: name
        kind: Text
        unique: true
      - name: slug
        regex: ^([a-z\d]+)(-[a-z\d]+)*$
        kind: Text
        unique: true
        optional: false

  - name: Protocol
    namespace: Security
    icon: mdi:security
    inherit_from: ["SecurityProtocolSpecifier"]
    display_labels:
      - name__value
    attributes:
      - name: number
        kind: Number
        unique: true
        optional: true

  - name: ProtocolSet
    namespace: Security
    icon: mdi:security
    inherit_from: ["SecurityProtocolSpecifier"]
    display_labels:
      - name__value
    relationships:
      - name: protocols
        peer: SecurityProtocol
        optional: true
        cardinality: many
        kind: Attribute

  - name: ACLRule
    namespace: Security
    icon: mdi:security
    inherit_from: ["SecurityRule"]
    attributes:
      - name: src_ports
        kind: Text
        regex: ^(\*|(\d+(-\d+)?)(,?(\d+(-\d+)?))*)$
        optional: false
      - name: dst_ports
        kind: Text
        regex: ^(\*|(\d+(-\d+)?)(,?(\d+(-\d+)?))*)$
        optional: false
    relationships:
      - name: protocols
        peer: SecurityProtocolSpecifier
        optional: false
        cardinality: many
        kind: Attribute
  - name: TailscaleSSHRule
    namespace: Security
    icon: mdi:security
    inherit_from: ["SecurityRule"]
    attributes:
      - name: check_period
        kind: Number
        optional: true
        default_value: 720
        min_value: 0
        max_value: 10080
      - name: accept_env
        kind: List
        optional: true
      - name: action
        optional: true
        kind: Dropdown
        default_value: allow
        choices:
          - label: allow
            name: allow
          - label: check
            name: check

  - name: RuleSet
    namespace: Security
    icon: mdi:security
    inherit_from: ["CoreArtifactTarget"]
    display_labels:
      - name__value
    attributes:
      - name: name
        kind: Text
        unique: true

    relationships:
      - name: rules
        peer: SecurityRule
        optional: true
        cardinality: many
        kind: Component

  - name: UserGroup
    inherit_from: ["SecurityIdentity", "SecurityDeviceGroupOwner"]
    namespace: Security
    icon: mdi:account-details
    display_labels:
      - name__value
    human_friendly_id:
      - "name__value"
    attributes:
      - name: name
        kind: Text
        unique: true
      - name: slug
        regex: ^([a-z\d]+)(-[a-z\d]+)*$
        kind: Text
        unique: true
        optional: false
      - name: description
        kind: TextArea
        optional: true
    relationships:
      - name: users
        peer: SecurityUser
        identifier: user_grouping
        optional: true
        cardinality: many
        kind: Attribute
      - name: groups
        peer: SecurityUserGroup
        direction: outbound
        optional: true
        cardinality: many
        kind: Attribute

  - name: User
    inherit_from: ["SecurityIdentity", "SecurityDeviceGroupOwner"]
    namespace: Security
    icon: mdi:account
    human_friendly_id:
      - email__value
    display_labels:
      - name__value
    attributes:
      - name: name
        kind: Text
        unique: true
      - name: email
        kind: Email
        unique: true
        optional: false
    relationships:
      - name: groups
        peer: SecurityUserGroup
        identifier: user_grouping
        optional: true
        cardinality: many
        kind: Attribute

  - name: IPAddress
    inherit_from: ["SecurityIdentity", "BuiltinIPAddress"]
    namespace: Security
    icon: mdi:ip

  - name: IPSubnet
    inherit_from: ["SecurityIdentity", "BuiltinIPPrefix"]
    namespace: Security
    icon: mdi:ip-network
    relationships:
      - name: subnets
        peer: SecurityIPSubnet
        optional: true
        cardinality: many
        kind: Attribute

  - name: IPGroup
    inherit_from: ["SecurityIdentity"]
    namespace: Security
    display_labels:
      - name__value
    attributes:
      - name: name
        kind: Text
        unique: true
      - name: slug
        regex: ^([a-z\d]+)(-[a-z\d]+)*$
        kind: Text
        unique: true
        optional: false
    relationships:
      - name: ip_addresses
        peer: SecurityIPAddress
        optional: true
        cardinality: many
        kind: Attribute
      - name: ip_subnets
        peer: SecurityIPSubnet
        optional: true
        cardinality: many
        kind: Attribute
      - name: groups
        peer: SecurityIPGroup
        optional: true
        direction: outbound
        cardinality: many
        kind: Attribute

  - name: DeviceGroup
    inherit_from: ["SecurityIdentity", "SecurityDeviceGroupOwner"]
    namespace: Security
    display_labels:
      - name__value
    attributes:
      - name: name
        kind: Text
        unique: true
      - name: slug
        regex: ^([a-z\d]+)(-[a-z\d]+)*$
        kind: Text
        unique: true
        optional: false
      - name: description
        kind: TextArea
        optional: true
    relationships:
      - name: devices
        peer: SecurityDevice
        optional: true
        cardinality: many
        kind: Attribute
      - name: groups
        peer: SecurityDeviceGroup
        optional: true
        cardinality: many
        kind: Attribute
        direction: outbound
      - name: owners
        peer: SecurityDeviceGroupOwner
        optional: true
        identifier: owner
        direction: outbound
        cardinality: many
        kind: Attribute

  - name: Device
    inherit_from: ["SecurityIdentity"]
    namespace: Security
    display_labels:
      - name__value
    attributes:
      - name: name
        kind: Text
        unique: true
    relationships:
      - name: device
        peer: DcimGenericDevice
        optional: false
        cardinality: one
        kind: Attribute
      - name: groups
        peer: SecurityDeviceGroup
        optional: true
        cardinality: many
        kind: Attribute

I could isolate the source of the issue in security-schema.yaml as this sample (line 151):

      - name: check_period
        kind: Number
        optional: true
        default_value: 720
        min_value: 0
        max_value: 10080

Commenting this block will suppress the error.

Additional Information

I am aware that the sample code provided above is not correct as min_value and max_value should not be configured this way.
Here, it is about improving error handling.

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/bugSomething isn't working as expected

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions