Beispiel #1
0
    def test_jobs_registration(self):
        """
        Check that plugin jobs are registered correctly and discoverable.
        """
        from dummy_plugin.jobs import DummyJob

        self.assertIn(DummyJob, registry.get("plugin_jobs", []))

        self.assertEqual(
            DummyJob,
            get_job("plugins/dummy_plugin.jobs/DummyJob"),
        )
        self.assertIn(
            "plugins/dummy_plugin.jobs/DummyJob",
            get_job_classpaths(),
        )
        jobs_dict = get_jobs()
        self.assertIn("plugins", jobs_dict)
        self.assertIn("dummy_plugin.jobs", jobs_dict["plugins"])
        self.assertEqual(
            "DummyPlugin jobs",
            jobs_dict["plugins"]["dummy_plugin.jobs"].get("name"),
        )
        self.assertIn("jobs", jobs_dict["plugins"]["dummy_plugin.jobs"])
        self.assertIn(
            "DummyJob",
            jobs_dict["plugins"]["dummy_plugin.jobs"]["jobs"],
        )
        self.assertEqual(
            DummyJob,
            jobs_dict["plugins"]["dummy_plugin.jobs"]["jobs"]["DummyJob"],
        )
Beispiel #2
0
    def test_git_datasource_contents_registration(self):
        """
        Check that plugin DatasourceContents are registered.
        """
        registered_datasources = registry.get("datasource_contents",
                                              {}).get("extras.gitrepository",
                                                      [])

        plugin_datasource = DatasourceContent(
            name="text files",
            content_identifier="dummy_plugin.textfile",
            icon="mdi-note-text",
            weight=1000,
            callback=refresh_git_text_files,
        )

        for datasource in registered_datasources:
            if datasource.name == plugin_datasource.name:
                self.assertEqual(datasource.content_identifier,
                                 plugin_datasource.content_identifier)
                self.assertEqual(datasource.icon, plugin_datasource.icon)
                self.assertEqual(datasource.weight, plugin_datasource.weight)
                self.assertEqual(datasource.callback,
                                 plugin_datasource.callback)
                break
        else:
            self.fail(
                f"Datasource {plugin_datasource.name} not found in registered_datasources!"
            )
Beispiel #3
0
    def test_jobs_registration(self):
        """
        Check that plugin jobs are registered correctly and discoverable.
        """
        from example_plugin.jobs import ExampleJob

        self.assertIn(ExampleJob, registry.get("plugin_jobs", []))

        self.assertEqual(
            ExampleJob,
            get_job("plugins/example_plugin.jobs/ExampleJob"),
        )
        self.assertIn(
            "plugins/example_plugin.jobs/ExampleJob",
            get_job_classpaths(),
        )
        jobs_dict = get_jobs()
        self.assertIn("plugins", jobs_dict)
        self.assertIn("example_plugin.jobs", jobs_dict["plugins"])
        self.assertEqual(
            "ExamplePlugin jobs",
            jobs_dict["plugins"]["example_plugin.jobs"].get("name"),
        )
        self.assertIn("jobs", jobs_dict["plugins"]["example_plugin.jobs"])
        self.assertIn(
            "ExampleJob",
            jobs_dict["plugins"]["example_plugin.jobs"]["jobs"],
        )
        self.assertEqual(
            ExampleJob,
            jobs_dict["plugins"]["example_plugin.jobs"]["jobs"]["ExampleJob"],
        )
Beispiel #4
0
    def test_extras_features_graphql(self):
        """
        Check that plugin GraphQL Types are registered.
        """
        registered_models = registry.get("model_features", {}).get("graphql", {})

        self.assertIn("dummy_plugin", registered_models.keys())
        self.assertIn("dummymodel", registered_models["dummy_plugin"])
Beispiel #5
0
    def test_git_datasource_contents(self):
        """
        Check that plugin DatasourceContents are registered.
        """
        registered_datasources = registry.get("datasource_contents", {}).get("extras.gitrepository", [])

        self.assertIn(
            DatasourceContent(
                name="text files",
                content_identifier="dummy_plugin.textfile",
                icon="mdi-note-text",
                callback=refresh_git_text_files,
            ),
            registered_datasources,
        )
Beispiel #6
0
def generate_query_mixin():
    """Generates and returns a class definition representing a GraphQL schema."""

    logger.info("Beginning generation of Nautobot GraphQL schema")

    class_attrs = {}

    def already_present(model):
        """Check if a model and its resolvers are staged to added to the Mixin."""

        single_item_name = str_to_var_name(model._meta.verbose_name)
        list_name = str_to_var_name(model._meta.verbose_name_plural)

        if single_item_name in class_attrs:
            logger.warning(
                f"Unable to register the schema single type '{single_item_name}' in GraphQL, "
                f"there is already another type {class_attrs[single_item_name]._type} registered under this name"
            )
            return True

        if list_name in class_attrs:
            logger.warning(
                f"Unable to register the schema list type '{list_name}' in GraphQL, "
                f"there is already another type {class_attrs[list_name]._type} registered under this name"
            )
            return True

        return False

    logger.debug(
        "Generating dynamic schemas for all models in the models_features graphql registry"
    )
    #  - Ensure an attribute/schematype with the same name doesn't already exist
    registered_models = registry.get("model_features", {}).get("graphql", {})
    for app_name, models in registered_models.items():
        for model_name in models:

            try:
                # Find the model class based on the content type
                ct = ContentType.objects.get(app_label=app_name,
                                             model=model_name)
                model = ct.model_class()
            except ContentType.DoesNotExist:
                logger.warning(
                    f"Unable to generate a schema type for the model '{app_name}.{model_name}' in GraphQL,"
                    "this model doesn't have an associated ContentType, please create the Object manually."
                )
                continue

            type_identifier = f"{app_name}.{model_name}"

            if type_identifier in registry["graphql_types"].keys():
                # Skip models that have been added statically
                continue

            schema_type = generate_schema_type(app_name=app_name, model=model)
            registry["graphql_types"][type_identifier] = schema_type

    logger.debug("Adding plugins' statically defined graphql schema types")
    # After checking for conflict
    for schema_type in registry["plugin_graphql_types"]:
        model = schema_type._meta.model
        type_identifier = f"{model._meta.app_label}.{model._meta.model_name}"

        if type_identifier in registry["graphql_types"]:
            logger.warning(
                f'Unable to load schema type for the model "{type_identifier}" as there is already another type '
                "registered under this name. If you are seeing this message during plugin development, check to "
                "make sure that you aren't using @extras_features(\"graphql\") on the same model you're also "
                "defining a custom GraphQL type for.")
        else:
            registry["graphql_types"][type_identifier] = schema_type

    logger.debug(
        "Extending all registered schema types with dynamic attributes")
    for schema_type in registry["graphql_types"].values():

        if already_present(schema_type._meta.model):
            continue

        schema_type = extend_schema_type(schema_type)
        class_attrs.update(generate_attrs_for_schema_type(schema_type))

    QueryMixin = type("QueryMixin", (object, ), class_attrs)
    logger.info("Generation of Nautobot GraphQL schema complete")
    return QueryMixin
Beispiel #7
0
def generate_query_mixin():
    """Generates and returns a class definition representing a GraphQL schema."""

    class_attrs = {}

    def already_present(model):
        """Check if a model and its resolvers are staged to added to the Mixin."""

        single_item_name = str_to_var_name(model._meta.verbose_name)
        list_name = str_to_var_name(model._meta.verbose_name_plural)

        if single_item_name in class_attrs:
            logger.warning(
                f"Unable to register the schema type '{single_item_name}' in GraphQL from '{app_name}':'{model_name}',"
                "there is already another type registered under this name")
            return True

        if list_name in class_attrs:
            logger.warning(
                f"Unable to register the schema type '{list_name}' in GraphQL from '{app_name}':'{model_name}',"
                "there is already another type registered under this name")
            return True

    # Generate SchemaType Dynamically for all Models registered in the model_features registry
    #  - Ensure an attribute/schematype with the same name doesn't already exist
    registered_models = registry.get("model_features", {}).get("graphql", {})
    for app_name, models in registered_models.items():
        for model_name in models:

            try:
                # Find the model class based on the content type
                ct = ContentType.objects.get(app_label=app_name,
                                             model=model_name)
                model = ct.model_class()
            except ContentType.DoesNotExist:
                logger.warning(
                    f"Unable to generate a schema type for the model '{app_name}.{model_name}' in GraphQL,"
                    "this model doesn't have an associated ContentType, please create the Object manually."
                )
                continue

            type_identifier = f"{app_name}.{model_name}"

            if type_identifier in registry["graphql_types"].keys():
                # Skip models that have been added statically
                continue

            schema_type = generate_schema_type(app_name=app_name, model=model)
            registry["graphql_types"][type_identifier] = schema_type

    # Add all objects in the plugin registry to the main registry
    # After checking for conflict
    for schema_type in registry["plugin_graphql_types"]:
        model = schema_type._meta.model
        type_identifier = f"{model._meta.app_label}.{model._meta.model_name}"

        if type_identifier not in registry["graphql_types"].keys():
            registry["graphql_types"][type_identifier] = schema_type

    # Extend schema_type with dynamic attributes for all object defined in the registry
    for schema_type in registry["graphql_types"].values():

        if already_present(schema_type._meta.model):
            continue

        schema_type = extend_schema_type(schema_type)
        class_attrs.update(generate_attrs_for_schema_type(schema_type))

    QueryMixin = type("QueryMixin", (object, ), class_attrs)
    return QueryMixin