opsmill / infrahub

Infrahub - A new approach to Infrastructure Management
https://opsmill.com/
GNU Affero General Public License v3.0
212 stars 18 forks source link

task: Problematic use of target names in ArtifactDefinition due to potential naming conflicts #1609

Open ogenstad opened 11 months ago

ogenstad commented 11 months ago

Component

API Server / GraphQL

Task Description

In relation to the ArtifactDefinition we define this generic object:

        {
            "name": "Group",
            "namespace": "Core",
            "description": "Generic Group Object.",
            "label": "Group",
            "default_filter": "name__value",
            "order_by": ["name__value"],
            "display_labels": ["label__value"],
            "include_in_menu": False,
            "branch": BranchSupportType.AWARE.value,
            "attributes": [
                {"name": "name", "kind": "Text", "unique": True},
                {"name": "label", "kind": "Text", "optional": True},
                {"name": "description", "kind": "Text", "optional": True},
            ],
            "relationships": [
                {
                    "name": "members",
                    "peer": "CoreNode",
                    "optional": True,
                    "identifier": "group_member",
                    "cardinality": "many",
                },
                {
                    "name": "subscribers",
                    "peer": "CoreNode",
                    "optional": True,
                    "identifier": "group_subscriber",
                    "cardinality": "many",
                },
            ],
        },

And these nodes that are tied to an artifact definition:

        {
            "name": "ArtifactDefinition",
            "namespace": "Core",
            "include_in_menu": False,
            "label": "Artifact Definition",
            "default_filter": "name__value",
            "order_by": ["name__value"],
            "display_labels": ["name__value"],
            "branch": BranchSupportType.AWARE.value,
            "attributes": [
                {"name": "name", "kind": "Text", "unique": True},
                {"name": "artifact_name", "kind": "Text"},
                {"name": "description", "kind": "Text", "optional": True},
                {"name": "parameters", "kind": "JSON"},
                {
                    "name": "content_type",
                    "kind": "Text",
                    "enum": ContentType.available_types(),
                },
            ],
            "relationships": [
                {
                    "name": "targets",
                    "peer": "CoreGroup",
                    "kind": "Attribute",
                    "identifier": "artifact_definition___group",
                    "cardinality": "one",
                    "optional": False,
                },
                {
                    "name": "transformation",
                    "peer": "CoreTransformation",
                    "kind": "Attribute",
                    "identifier": "artifact_definition___transformation",
                    "cardinality": "one",
                    "optional": False,
                },
            ],
        },
        {
            "name": "StandardGroup",
            "namespace": "Core",
            "description": "Group of nodes of any kind.",
            "include_in_menu": True,
            "icon": "mdi:account-group",
            "label": "Standard Group",
            "default_filter": "name__value",
            "order_by": ["name__value"],
            "display_labels": ["name__value"],
            "branch": BranchSupportType.AWARE.value,
            "inherit_from": ["CoreGroup"],
        },

Within the example scripts for infrastructure_edge.py we create a number of StandardGroups and then refer to these from the infrahub-edge repository:

artifact_definitions:
  - name: "Openconfig Interface for Arista devices"
    artifact_name: "openconfig-interfaces"
    parameters:
      device: "name__value"
    content_type: "application/json"
    targets: "arista_devices"
    transformation: "OCInterfaces"

The assumption here is that arista_devices would be a unique name for this group. However we don't have any such guarantee. While we can ensure that StandardGroup won't have other groups that might have the same name.

I.e. we can have a query that looks like this:

query MyQuery {
  CoreGroup(name__value: "artisans") {
    edges {
      node {
        __typename
        name {
          value
        }
      }
    }
  }
}

Response:

{
  "data": {
    "CoreGroup": {
      "edges": [
        {
          "node": {
            "__typename": "CoreStandardGroup",
            "name": {
              "value": "artisans"
            }
          }
        },
        {
          "node": {
            "__typename": "RpgParty",
            "name": {
              "value": "artisans"
            }
          }
        }
      ]
    }
  }
}

While I haven't tested to see what happens this feels problematic and it could cause random errors etc. The best solution might be to force users to specify the type of group instead of just any group coming from "CoreGroup".

dgarros commented 11 months ago

I think there are a couple of changes we could do to improve that.

ogenstad commented 11 months ago

I'm not sure we want to enforce unique attributes in that way. For instance with groups I think we might want to be able to have the same name for different type of groups.

Don't quite get what you mean with the filter and how that would help here, would need some clarity there.