This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new f1e1cdcc3b Add option for storing configuration description in 
providers (#32629)
f1e1cdcc3b is described below

commit f1e1cdcc3b2826e68ba133f350300b5065bbca33
Author: Jarek Potiuk <[email protected]>
AuthorDate: Sun Jul 16 17:09:09 2023 +0200

    Add option for storing configuration description in providers (#32629)
    
    This is mostly for the capacity of adding configuration to
    provider.yaml files.
    
    This change adds capavilty of adding "config" option to provider
    yaml and provider_info. This is not yet used, but it has been
    extracted as separate PR from #32604 in an attempt to make it more
    reviewable and readable.
---
 airflow/provider.yaml.schema.json | 710 +++++++++++++++++++++-----------------
 airflow/provider_info.schema.json | 285 +++++++++------
 airflow/providers_manager.py      |  45 ++-
 3 files changed, 630 insertions(+), 410 deletions(-)

diff --git a/airflow/provider.yaml.schema.json 
b/airflow/provider.yaml.schema.json
index a1d0822af6..509e5dfce6 100644
--- a/airflow/provider.yaml.schema.json
+++ b/airflow/provider.yaml.schema.json
@@ -1,345 +1,437 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#";,
-  "type": "object",
-  "properties": {
-    "package-name": {
-      "description": "Package name available under which the package is 
available in the PyPI repository.",
-      "type": "string"
-    },
-    "name": {
-      "description": "Provider name",
-      "type": "string"
-    },
-    "description": {
-      "description": "Information about the package in RST format",
-      "type": "string"
-    },
-    "versions": {
-      "description": "List of available versions in PyPI. Sorted descending 
according to release date.",
-      "type": "array",
-      "items": {
-        "type": "string"
-      }
-    },
-    "suspended": {
-      "description": "If set to true, the provider is suspended and it's not a 
candidate for release nor contributes dependencies to constraint 
calculations/CI image. Tests are excluded.",
-      "type:": "boolean"
-    },
-    "dependencies": {
-      "description": "Dependencies that should be added to the provider",
-      "type": "array",
-      "items": {
-        "type": "string"
-      }
-    },
-    "excluded-python-versions": {
-      "description": "List of python versions excluded for that provider",
-      "type": "array",
-      "items": {
-          "type": "string"
-      }
-    },
-    "integrations": {
-      "description": "List of integrations supported by the provider.",
-      "type": "array",
-      "items": {
-        "type": "object",
-        "properties": {
-          "integration-name": {
-            "type": "string",
-            "description": "Name of the integration."
-          },
-          "external-doc-url": {
-            "type": "string",
-            "description": "URL to external documentation for the integration."
-          },
-          "how-to-guide": {
-            "description": "List of paths to how-to-guide for the integration. 
The path must start with '/docs/'",
+    "$schema": "http://json-schema.org/draft-07/schema#";,
+    "type": "object",
+    "properties": {
+        "package-name": {
+            "description": "Package name available under which the package is 
available in the PyPI repository.",
+            "type": "string"
+        },
+        "name": {
+            "description": "Provider name",
+            "type": "string"
+        },
+        "description": {
+            "description": "Information about the package in RST format",
+            "type": "string"
+        },
+        "versions": {
+            "description": "List of available versions in PyPI. Sorted 
descending according to release date.",
             "type": "array",
             "items": {
-              "type": "string"
+                "type": "string"
             }
-          },
-          "logo": {
-            "description": "Path to the logo for the integration. The path 
must start with '/integration-logos/'",
-            "type": "string"
-          },
-          "tags": {
-            "description": "List of tags describing the integration. While 
we're using RST, only one tag is supported per integration.",
+        },
+        "suspended": {
+            "description": "If set to true, the provider is suspended and it's 
not a candidate for release nor contributes dependencies to constraint 
calculations/CI image. Tests are excluded.",
+            "type:": "boolean"
+        },
+        "dependencies": {
+            "description": "Dependencies that should be added to the provider",
             "type": "array",
             "items": {
-              "type": "string",
-              "enum": [
-                "alibaba",
-                "apache",
-                "aws",
-                "azure",
-                "dbt",
-                "gcp",
-                "gmp",
-                "google",
-                "kafka",
-                "protocol",
-                "service",
-                "software",
-                "yandex"
-              ]
-            },
-            "minItems": 1,
-            "maxItems": 1
-          }
+                "type": "string"
+            }
         },
-        "additionalProperties": false,
-        "required": [
-          "integration-name",
-          "external-doc-url",
-          "tags"
-        ]
-      }
-    },
-    "operators": {
-      "type": "array",
-      "items": {
-        "type": "object",
-        "properties": {
-          "integration-name": {
-            "type": "string",
-            "description": "Integration name. It must have a matching item in 
the 'integration' section of any provider."
-          },
-          "python-modules": {
-            "description": "List of python modules containing the operators.",
+        "excluded-python-versions": {
+            "description": "List of python versions excluded for that 
provider",
+            "type": "array",
+            "items": {
+                "type": "string"
+            }
+        },
+        "integrations": {
+            "description": "List of integrations supported by the provider.",
             "type": "array",
             "items": {
-              "type": "string"
+                "type": "object",
+                "properties": {
+                    "integration-name": {
+                        "type": "string",
+                        "description": "Name of the integration."
+                    },
+                    "external-doc-url": {
+                        "type": "string",
+                        "description": "URL to external documentation for the 
integration."
+                    },
+                    "how-to-guide": {
+                        "description": "List of paths to how-to-guide for the 
integration. The path must start with '/docs/'",
+                        "type": "array",
+                        "items": {
+                            "type": "string"
+                        }
+                    },
+                    "logo": {
+                        "description": "Path to the logo for the integration. 
The path must start with '/integration-logos/'",
+                        "type": "string"
+                    },
+                    "tags": {
+                        "description": "List of tags describing the 
integration. While we're using RST, only one tag is supported per integration.",
+                        "type": "array",
+                        "items": {
+                            "type": "string",
+                            "enum": [
+                                "alibaba",
+                                "apache",
+                                "aws",
+                                "azure",
+                                "dbt",
+                                "gcp",
+                                "gmp",
+                                "google",
+                                "kafka",
+                                "protocol",
+                                "service",
+                                "software",
+                                "yandex"
+                            ]
+                        },
+                        "minItems": 1,
+                        "maxItems": 1
+                    }
+                },
+                "additionalProperties": false,
+                "required": [
+                    "integration-name",
+                    "external-doc-url",
+                    "tags"
+                ]
             }
-          }
         },
-        "additionalProperties": false,
-        "required": [
-          "integration-name",
-          "python-modules"
-        ]
-      }
-    },
-    "sensors": {
-      "type": "array",
-      "items": {
-        "type": "object",
-        "properties": {
-          "integration-name": {
-            "type": "string",
-            "description": "Integration name. It must have a matching item in 
the 'integration' section of any provider."
-          },
-          "python-modules": {
-            "description": "List of python modules containing the sensors.",
+        "operators": {
             "type": "array",
             "items": {
-              "type": "string"
+                "type": "object",
+                "properties": {
+                    "integration-name": {
+                        "type": "string",
+                        "description": "Integration name. It must have a 
matching item in the 'integration' section of any provider."
+                    },
+                    "python-modules": {
+                        "description": "List of python modules containing the 
operators.",
+                        "type": "array",
+                        "items": {
+                            "type": "string"
+                        }
+                    }
+                },
+                "additionalProperties": false,
+                "required": [
+                    "integration-name",
+                    "python-modules"
+                ]
             }
-          }
         },
-        "required": [
-          "integration-name",
-          "python-modules"
-        ],
-        "additionalProperties": true
-      }
-    },
-    "hooks": {
-      "type": "array",
-      "items": {
-        "type": "object",
-        "properties": {
-          "integration-name": {
-            "type": "string",
-            "description": "Integration name. It must have a matching item in 
the 'integration' section of any provider."
-          },
-          "python-modules": {
-            "description": "List of python modules containing the hooks.",
+        "sensors": {
             "type": "array",
             "items": {
-              "type": "string"
+                "type": "object",
+                "properties": {
+                    "integration-name": {
+                        "type": "string",
+                        "description": "Integration name. It must have a 
matching item in the 'integration' section of any provider."
+                    },
+                    "python-modules": {
+                        "description": "List of python modules containing the 
sensors.",
+                        "type": "array",
+                        "items": {
+                            "type": "string"
+                        }
+                    }
+                },
+                "required": [
+                    "integration-name",
+                    "python-modules"
+                ],
+                "additionalProperties": true
             }
-          }
         },
-        "additionalProperties": false,
-        "required": [
-          "integration-name",
-          "python-modules"
-        ]
-      }
-    },
-    "transfers": {
-      "type": "array",
-      "items": {
-        "type": "object",
-        "properties": {
-          "how-to-guide": {
-            "description": "Path to how-to-guide for the transfer. The path 
must start with '/docs/'",
-            "type": "string"
-          },
-          "source-integration-name": {
-            "type": "string",
-            "description": "Integration name. It must have a matching item in 
the 'integration' section of any provider."
-          },
-          "target-integration-name": {
-            "type": "string",
-            "description": "Target integration name. It must have a matching 
item in the 'integration' section of any provider."
-          },
-          "python-module": {
-            "type": "string",
-            "description": "List of python modules containing the transfers."
-          }
+        "hooks": {
+            "type": "array",
+            "items": {
+                "type": "object",
+                "properties": {
+                    "integration-name": {
+                        "type": "string",
+                        "description": "Integration name. It must have a 
matching item in the 'integration' section of any provider."
+                    },
+                    "python-modules": {
+                        "description": "List of python modules containing the 
hooks.",
+                        "type": "array",
+                        "items": {
+                            "type": "string"
+                        }
+                    }
+                },
+                "additionalProperties": false,
+                "required": [
+                    "integration-name",
+                    "python-modules"
+                ]
+            }
         },
-        "additionalProperties": false,
-        "required": [
-          "source-integration-name",
-          "target-integration-name",
-          "python-module"
-        ]
-      }
-    },
-    "triggers": {
-      "type": "array",
-      "items": {
-        "type": "object",
-        "properties": {
-          "integration-name": {
-            "type": "string",
-            "description": "Integration name. It must have a matching item in 
the 'integration' section of any provider."
-          },
-          "python-modules": {
-            "description": "List of Python modules containing the triggers.",
+        "transfers": {
             "type": "array",
             "items": {
-              "type": "string"
+                "type": "object",
+                "properties": {
+                    "how-to-guide": {
+                        "description": "Path to how-to-guide for the transfer. 
The path must start with '/docs/'",
+                        "type": "string"
+                    },
+                    "source-integration-name": {
+                        "type": "string",
+                        "description": "Integration name. It must have a 
matching item in the 'integration' section of any provider."
+                    },
+                    "target-integration-name": {
+                        "type": "string",
+                        "description": "Target integration name. It must have 
a matching item in the 'integration' section of any provider."
+                    },
+                    "python-module": {
+                        "type": "string",
+                        "description": "List of python modules containing the 
transfers."
+                    }
+                },
+                "additionalProperties": false,
+                "required": [
+                    "source-integration-name",
+                    "target-integration-name",
+                    "python-module"
+                ]
             }
-          }
         },
-        "additionalProperties": false,
-        "required": [
-          "integration-name",
-          "python-modules"
-        ]
-      }
-    },
-    "connection-types": {
-      "type": "array",
-      "description": "Array of connection types mapped to hook class names",
-      "items": {
-          "type": "object",
-          "properties": {
-              "connection-type": {
-                  "description": "Type of connection defined by the provider",
-                  "type": "string"
-              },
-              "hook-class-name": {
-                  "description": "Hook class name that implements the 
connection type",
-                  "type": "string"
-              }
-          },
-          "required": [
-              "connection-type",
-              "hook-class-name"
-          ]
-      }
-    },
-    "extra-links": {
-      "type": "array",
-      "description": "Operator class names that provide extra link 
functionality",
-      "items": {
-        "type": "string"
-      }
-    },
-    "additional-extras": {
-      "type": "array",
-      "items": {
-        "type": "object",
-        "properties": {
-          "name": {
-            "description": "Name of the extra",
-            "type": "string"
-          },
-          "dependencies": {
-            "description": "Dependencies that should be added for the extra",
+        "triggers": {
             "type": "array",
             "items": {
-              "type": "string"
+                "type": "object",
+                "properties": {
+                    "integration-name": {
+                        "type": "string",
+                        "description": "Integration name. It must have a 
matching item in the 'integration' section of any provider."
+                    },
+                    "python-modules": {
+                        "description": "List of Python modules containing the 
triggers.",
+                        "type": "array",
+                        "items": {
+                            "type": "string"
+                        }
+                    }
+                },
+                "additionalProperties": false,
+                "required": [
+                    "integration-name",
+                    "python-modules"
+                ]
             }
-          }
         },
-        "required": [ "name", "dependencies"]
-      },
-
-      "description": "Additional extras that the provider should have. 
Replaces auto-generated cross-provider extras, if matching the same prefix, so 
that you can specify boundaries for existing dependencies."
-    },
-    "task-decorators": {
-        "type": "array",
-        "description": "Decorators to use with the TaskFlow API. Can be 
accessed by users via '@task.<name>'",
-        "items": {
-            "name": {
+        "connection-types": {
+            "type": "array",
+            "description": "Array of connection types mapped to hook class 
names",
+            "items": {
+                "type": "object",
+                "properties": {
+                    "connection-type": {
+                        "description": "Type of connection defined by the 
provider",
+                        "type": "string"
+                    },
+                    "hook-class-name": {
+                        "description": "Hook class name that implements the 
connection type",
+                        "type": "string"
+                    }
+                },
+                "required": [
+                    "connection-type",
+                    "hook-class-name"
+                ]
+            }
+        },
+        "extra-links": {
+            "type": "array",
+            "description": "Operator class names that provide extra link 
functionality",
+            "items": {
                 "type": "string"
+            }
+        },
+        "additional-extras": {
+            "type": "array",
+            "items": {
+                "type": "object",
+                "properties": {
+                    "name": {
+                        "description": "Name of the extra",
+                        "type": "string"
+                    },
+                    "dependencies": {
+                        "description": "Dependencies that should be added for 
the extra",
+                        "type": "array",
+                        "items": {
+                            "type": "string"
+                        }
+                    }
+                },
+                "required": [
+                    "name",
+                    "dependencies"
+                ]
             },
-            "path": {
+            "description": "Additional extras that the provider should have. 
Replaces auto-generated cross-provider extras, if matching the same prefix, so 
that you can specify boundaries for existing dependencies."
+        },
+        "task-decorators": {
+            "type": "array",
+            "description": "Decorators to use with the TaskFlow API. Can be 
accessed by users via '@task.<name>'",
+            "items": {
+                "name": {
+                    "type": "string"
+                },
+                "path": {
+                    "type": "string"
+                }
+            }
+        },
+        "secrets-backends": {
+            "type": "array",
+            "description": "Secrets Backend class names",
+            "items": {
                 "type": "string"
             }
+        },
+        "logging": {
+            "type": "array",
+            "description": "Logging Task Handlers class names",
+            "items": {
+                "type": "string"
+            }
+        },
+        "auth-backends": {
+            "type": "array",
+            "description": "API Auth Backend module names",
+            "items": {
+                "type": "string"
+            }
+        },
+        "notifications": {
+            "type": "array",
+            "description": "Notification class names",
+            "items": {
+                "type": "string"
+            }
+        },
+        "executors": {
+            "type": "array",
+            "description": "Executor class names",
+            "items": {
+                "type": "string"
+            }
+        },
+        "config": {
+            "type": "object",
+            "additionalProperties": {
+                "type": "object",
+                "properties": {
+                    "description": {
+                        "type": [
+                            "string",
+                            "null"
+                        ]
+                    },
+                    "options": {
+                        "type": "object",
+                        "additionalProperties": {
+                            "$ref": "#/definitions/option"
+                        }
+                    },
+                    "renamed": {
+                        "type": "object",
+                        "properties": {
+                            "previous_name": {
+                                "type": "string"
+                            },
+                            "version": {
+                                "type": "string"
+                            }
+                        }
+                    }
+                },
+                "required": [
+                    "description",
+                    "options"
+                ],
+                "additionalProperties": false
+            }
+        },
+        "plugins": {
+            "type": "array",
+            "description": "Plugins exposed by the provider",
+            "items": {
+                "name": {
+                    "type": "string"
+                },
+                "plugin-class": {
+                    "type": "string"
+                }
+            }
         }
     },
-    "secrets-backends": {
-      "type": "array",
-      "description": "Secrets Backend class names",
-      "items": {
-          "type": "string"
-      }
-    },
-    "logging": {
-      "type": "array",
-      "description": "Logging Task Handlers class names",
-      "items": {
-          "type": "string"
-      }
-    },
-    "auth-backends": {
-      "type": "array",
-      "description": "API Auth Backend module names",
-      "items": {
-          "type": "string"
-      }
-    },
-    "notifications": {
-          "type": "array",
-          "description": "Notification class names",
-          "items": {
-              "type": "string"
-          }
-    },
-    "executors": {
-          "type": "array",
-          "description": "Executor class names",
-          "items": {
-              "type": "string"
-          }
-      },
-    "plugins": {
-      "type": "array",
-      "description": "Plugins exposed by the provider",
-      "items": {
-        "name": {
-           "type": "string"
-        },
-        "plugin-class": {
-           "type": "string"
+    "additionalProperties": false,
+    "definitions": {
+        "option": {
+            "type": "object",
+            "properties": {
+                "description": {
+                    "type": [
+                        "string",
+                        "null"
+                    ]
+                },
+                "version_added": {
+                    "type": [
+                        "string",
+                        "null"
+                    ]
+                },
+                "type": {
+                    "type": "string",
+                    "enum": [
+                        "string",
+                        "boolean",
+                        "integer",
+                        "float"
+                    ]
+                },
+                "example": {
+                    "type": [
+                        "string",
+                        "null",
+                        "number"
+                    ]
+                },
+                "default": {
+                    "type": [
+                        "string",
+                        "null",
+                        "number"
+                    ]
+                },
+                "sensitive": {
+                    "type": "boolean",
+                    "description": "When true, this option is sensitive and 
can be specified using AIRFLOW__{section}___{name}__SECRET or 
AIRFLOW__{section}___{name}_CMD environment variables. See: 
airflow.configuration.AirflowConfigParser.sensitive_config_values"
+                }
+            },
+            "required": [
+                "description",
+                "version_added",
+                "type",
+                "example",
+                "default"
+            ],
+            "additional_properties": false
         }
-      }
-    }
-  },
-  "additionalProperties": false,
-  "required": [
-    "name",
-    "package-name",
-    "description",
-    "suspended",
-    "dependencies",
-    "versions"
-  ]
+    },
+    "required": [
+        "name",
+        "package-name",
+        "description",
+        "suspended",
+        "dependencies",
+        "versions"
+    ]
 }
diff --git a/airflow/provider_info.schema.json 
b/airflow/provider_info.schema.json
index 86b0430cc3..9a5dcaefbe 100644
--- a/airflow/provider_info.schema.json
+++ b/airflow/provider_info.schema.json
@@ -1,105 +1,198 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#";,
-  "type": "object",
-  "properties": {
-    "package-name": {
-      "description": "Package name available under which the package is 
available in the PyPI repository.",
-      "type": "string"
-    },
-    "name": {
-      "description": "Provider name",
-      "type": "string"
-    },
-    "description": {
-      "description": "Information about the package in RST format",
-      "type": "string"
-    },
-    "hook-class-names": {
-      "type": "array",
-      "description": "Hook class names that provide connection types to core 
(deprecated by connection-types)",
-      "items": {
-        "type": "string"
-      },
-      "deprecated": {
-        "description": "The hook-class-names property has been deprecated in 
favour of connection-types which is more performant version allowing to only 
import individual Hooks rather than all hooks at once",
-        "deprecatedVersion": "2.2.0"
-      }
-    },
-    "connection-types": {
-      "type": "array",
-      "description": "Map of connection types mapped to hook class names.",
-      "items": {
-        "type": "object",
-        "properties": {
-          "connection-type": {
-            "description": "Type of connection defined by the provider",
+    "$schema": "http://json-schema.org/draft-07/schema#";,
+    "type": "object",
+    "properties": {
+        "package-name": {
+            "description": "Package name available under which the package is 
available in the PyPI repository.",
             "type": "string"
-          },
-          "hook-class-name": {
-            "description": "Hook class name that implements the connection 
type",
+        },
+        "name": {
+            "description": "Provider name",
             "type": "string"
-          }
-        }
-      },
-      "required": ["connection-type", "hook-class-name"]
-    },
-    "extra-links": {
-      "type": "array",
-      "description": "Operator class names that provide extra link 
functionality",
-      "items": {
-        "type": "string"
-      }
-    },
-    "secrets-backends": {
-      "type": "array",
-      "description": "Secrets Backend class names",
-      "items": {
-        "type": "string"
-      }
-    },
-    "logging": {
-      "type": "array",
-      "description": "Logging Task Handlers class names",
-      "items": {
-          "type": "string"
-      }
-    },
-    "auth-backends": {
-      "type": "array",
-      "description": "API Auth Backend module names",
-      "items": {
-          "type": "string"
-      }
-    },
-    "notifications": {
-          "type": "array",
-          "description": "Notification class names",
-          "items": {
-              "type": "string"
-          }
-    },
-    "executors": {
-          "type": "array",
-          "description": "Executor class names",
-          "items": {
-              "type": "string"
-          }
-    },
-    "task-decorators": {
-        "type": "array",
-        "description": "Apply custom decorators to the TaskFlow API. Can be 
accessed by users via '@task.<name>'",
-        "items": {
-            "name": {
+        },
+        "description": {
+            "description": "Information about the package in RST format",
+            "type": "string"
+        },
+        "hook-class-names": {
+            "type": "array",
+            "description": "Hook class names that provide connection types to 
core (deprecated by connection-types)",
+            "items": {
                 "type": "string"
             },
-            "path": {
+            "deprecated": {
+                "description": "The hook-class-names property has been 
deprecated in favour of connection-types which is more performant version 
allowing to only import individual Hooks rather than all hooks at once",
+                "deprecatedVersion": "2.2.0"
+            }
+        },
+        "connection-types": {
+            "type": "array",
+            "description": "Map of connection types mapped to hook class 
names.",
+            "items": {
+                "type": "object",
+                "properties": {
+                    "connection-type": {
+                        "description": "Type of connection defined by the 
provider",
+                        "type": "string"
+                    },
+                    "hook-class-name": {
+                        "description": "Hook class name that implements the 
connection type",
+                        "type": "string"
+                    }
+                }
+            },
+            "required": [
+                "connection-type",
+                "hook-class-name"
+            ]
+        },
+        "extra-links": {
+            "type": "array",
+            "description": "Operator class names that provide extra link 
functionality",
+            "items": {
                 "type": "string"
             }
+        },
+        "secrets-backends": {
+            "type": "array",
+            "description": "Secrets Backend class names",
+            "items": {
+                "type": "string"
+            }
+        },
+        "logging": {
+            "type": "array",
+            "description": "Logging Task Handlers class names",
+            "items": {
+                "type": "string"
+            }
+        },
+        "auth-backends": {
+            "type": "array",
+            "description": "API Auth Backend module names",
+            "items": {
+                "type": "string"
+            }
+        },
+        "notifications": {
+            "type": "array",
+            "description": "Notification class names",
+            "items": {
+                "type": "string"
+            }
+        },
+        "executors": {
+            "type": "array",
+            "description": "Executor class names",
+            "items": {
+                "type": "string"
+            }
+        },
+        "config": {
+            "type": "object",
+            "additionalProperties": {
+                "type": "object",
+                "properties": {
+                    "description": {
+                        "type": [
+                            "string",
+                            "null"
+                        ]
+                    },
+                    "options": {
+                        "type": "object",
+                        "additionalProperties": {
+                            "$ref": "#/definitions/option"
+                        }
+                    },
+                    "renamed": {
+                        "type": "object",
+                        "properties": {
+                            "previous_name": {
+                                "type": "string"
+                            },
+                            "version": {
+                                "type": "string"
+                            }
+                        }
+                    }
+                },
+                "required": [
+                    "description",
+                    "options"
+                ],
+                "additionalProperties": false
+            }
+        },
+        "task-decorators": {
+            "type": "array",
+            "description": "Apply custom decorators to the TaskFlow API. Can 
be accessed by users via '@task.<name>'",
+            "items": {
+                "name": {
+                    "type": "string"
+                },
+                "path": {
+                    "type": "string"
+                }
+            }
         }
-    }
-  },
-  "required": [
-    "name",
-    "description"
-  ]
+    },
+    "definitions": {
+        "option": {
+            "type": "object",
+            "properties": {
+                "description": {
+                    "type": [
+                        "string",
+                        "null"
+                    ]
+                },
+                "version_added": {
+                    "type": [
+                        "string",
+                        "null"
+                    ]
+                },
+                "type": {
+                    "type": "string",
+                    "enum": [
+                        "string",
+                        "boolean",
+                        "integer",
+                        "float"
+                    ]
+                },
+                "example": {
+                    "type": [
+                        "string",
+                        "null",
+                        "number"
+                    ]
+                },
+                "default": {
+                    "type": [
+                        "string",
+                        "null",
+                        "number"
+                    ]
+                },
+                "sensitive": {
+                    "type": "boolean",
+                    "description": "When true, this option is sensitive and 
can be specified using AIRFLOW__{section}___{name}__SECRET or 
AIRFLOW__{section}___{name}_CMD environment variables. See: 
airflow.configuration.AirflowConfigParser.sensitive_config_values"
+                }
+            },
+            "required": [
+                "description",
+                "version_added",
+                "type",
+                "example",
+                "default"
+            ],
+            "additional_properties": false
+        }
+    },
+    "required": [
+        "name",
+        "description"
+    ]
 }
diff --git a/airflow/providers_manager.py b/airflow/providers_manager.py
index abd14d27b5..4f2f063599 100644
--- a/airflow/providers_manager.py
+++ b/airflow/providers_manager.py
@@ -130,12 +130,23 @@ class LazyDictWithCache(MutableMapping):
         return key in self._raw_dict
 
 
+def _read_schema_from_resources_or_local_file(filename: str) -> dict:
+    try:
+        with resource_files("airflow").joinpath(filename).open("rb") as f:
+            schema = json.load(f)
+    except FileNotFoundError:
+        import pathlib
+
+        with (pathlib.Path(__file__).parent / filename).open("rb") as f:
+            schema = json.load(f)
+    return schema
+
+
 def _create_provider_info_schema_validator():
     """Creates JSON schema validator from the provider_info.schema.json."""
     import jsonschema
 
-    with 
resource_files("airflow").joinpath("provider_info.schema.json").open("rb") as f:
-        schema = json.load(f)
+    schema = 
_read_schema_from_resources_or_local_file("provider_info.schema.json")
     cls = jsonschema.validators.validator_for(schema)
     validator = cls(schema)
     return validator
@@ -145,8 +156,7 @@ def 
_create_customized_form_field_behaviours_schema_validator():
     """Creates JSON schema validator from the 
customized_form_field_behaviours.schema.json."""
     import jsonschema
 
-    with 
resource_files("airflow").joinpath("customized_form_field_behaviours.schema.json").open("rb")
 as f:
-        schema = json.load(f)
+    schema = 
_read_schema_from_resources_or_local_file("customized_form_field_behaviours.schema.json")
     cls = jsonschema.validators.validator_for(schema)
     validator = cls(schema)
     return validator
@@ -390,6 +400,7 @@ class ProvidersManager(LoggingMixin, metaclass=Singleton):
         self._logging_class_name_set: set[str] = set()
         self._secrets_backend_class_name_set: set[str] = set()
         self._executor_class_name_set: set[str] = set()
+        self._provider_configs: dict[str, dict[str, Any]] = {}
         self._api_auth_backend_module_names: set[str] = set()
         self._trigger_info_set: set[TriggerInfo] = set()
         self._provider_schema_validator = 
_create_provider_info_schema_validator()
@@ -462,6 +473,16 @@ class ProvidersManager(LoggingMixin, metaclass=Singleton):
         self.initialize_providers_list()
         self._discover_executors()
 
+    @provider_info_cache("config")
+    def initialize_providers_configuration(self):
+        """Lazy initialization of providers configuration information."""
+        self.initialize_providers_list()
+        self._discover_config()
+        # Now update conf with the new provider configuration from providers
+        from airflow.configuration import conf
+
+        conf.load_provider_configuration()
+
     @provider_info_cache("auth_backends")
     def initialize_providers_auth_backends(self):
         """Lazy initialization of providers API auth_backends information."""
@@ -554,7 +575,6 @@ class ProvidersManager(LoggingMixin, metaclass=Singleton):
             with open(path) as provider_yaml_file:
                 provider_info = yaml.safe_load(provider_yaml_file)
             self._provider_schema_validator.validate(provider_info)
-
             version = provider_info["versions"][0]
             if package_name not in self._provider_dict:
                 self._provider_dict[package_name] = ProviderInfo(version, 
provider_info, "source")
@@ -965,6 +985,12 @@ class ProvidersManager(LoggingMixin, metaclass=Singleton):
                     if _correctness_check(provider_package, 
executors_class_name, provider):
                         self._executor_class_name_set.add(executors_class_name)
 
+    def _discover_config(self) -> None:
+        """Retrieve all configs defined in the providers."""
+        for provider_package, provider in self._provider_dict.items():
+            if provider.data.get("config"):
+                self._provider_configs[provider_package] = 
provider.data.get("config")
+
     @provider_info_cache("triggers")
     def initialize_providers_triggers(self):
         """Initialization of providers triggers."""
@@ -1053,3 +1079,12 @@ class ProvidersManager(LoggingMixin, 
metaclass=Singleton):
     def executor_class_names(self) -> list[str]:
         self.initialize_providers_executors()
         return sorted(self._executor_class_name_set)
+
+    @property
+    def provider_configs(self) -> list[tuple[str, dict[str, Any]]]:
+        self.initialize_providers_configuration()
+        return sorted(self._provider_configs.items(), key=lambda x: x[0])
+
+    @property
+    def already_initialized_provider_configs(self) -> list[tuple[str, 
dict[str, Any]]]:
+        return sorted(self._provider_configs.items(), key=lambda x: x[0])


Reply via email to