From 9be4026b6ffa257b9a3f1eb8d048ecbb164caa4f Mon Sep 17 00:00:00 2001 From: Elad Kalif <45845474+eladkal@users.noreply.github.com> Date: Sun, 21 Apr 2024 10:55:02 +0300 Subject: [PATCH] Add documentation for packages - 2024-04-16 (#1007) --- .../8.1.1/.buildinfo | 4 + .../cncf/kubernetes/callbacks/index.html | 1081 ++ .../cncf/kubernetes/decorators/index.html | 901 ++ .../decorators/kubernetes/index.html | 937 ++ .../cncf/kubernetes/executors/index.html | 904 ++ .../executors/kubernetes_executor/index.html | 1140 ++ .../kubernetes_executor_types/index.html | 924 ++ .../kubernetes_executor_utils/index.html | 1133 ++ .../local_kubernetes_executor/index.html | 1183 ++ .../cncf/kubernetes/hooks/index.html | 901 ++ .../kubernetes/hooks/kubernetes/index.html | 1558 +++ .../providers/cncf/kubernetes/index.html | 978 ++ .../cncf/kubernetes/k8s_model/index.html | 984 ++ .../cncf/kubernetes/kube_client/index.html | 968 ++ .../cncf/kubernetes/kube_config/index.html | 942 ++ .../kubernetes_executor_templates/index.html | 890 ++ .../kubernetes_helper_functions/index.html | 1035 ++ .../custom_object_launcher/index.html | 1126 ++ .../cncf/kubernetes/operators/index.html | 906 ++ .../cncf/kubernetes/operators/job/index.html | 1257 ++ .../operators/kubernetes_pod/index.html | 893 ++ .../cncf/kubernetes/operators/pod/index.html | 1355 ++ .../kubernetes/operators/resource/index.html | 983 ++ .../operators/spark_kubernetes/index.html | 1116 ++ .../cncf/kubernetes/pod_generator/index.html | 1332 ++ .../pod_generator_deprecated/index.html | 1121 ++ .../pod_launcher_deprecated/index.html | 1093 ++ .../pod_template_file_examples/index.html | 890 ++ .../python_kubernetes_script/index.html | 952 ++ .../resource_convert/configmap/index.html | 956 ++ .../resource_convert/env_variable/index.html | 935 ++ .../kubernetes/resource_convert/index.html | 903 ++ .../resource_convert/secret/index.html | 956 ++ .../cncf/kubernetes/secret/index.html | 976 ++ .../cncf/kubernetes/sensors/index.html | 901 ++ .../sensors/spark_kubernetes/index.html | 981 ++ .../kubernetes/template_rendering/index.html | 936 ++ .../cncf/kubernetes/triggers/index.html | 903 ++ .../cncf/kubernetes/triggers/job/index.html | 967 ++ .../triggers/kubernetes_pod/index.html | 893 ++ .../cncf/kubernetes/triggers/pod/index.html | 1041 ++ .../kubernetes/utils/delete_from/index.html | 974 ++ .../cncf/kubernetes/utils/index.html | 904 ++ .../utils/k8s_resource_iterator/index.html | 925 ++ .../kubernetes/utils/pod_manager/index.html | 1423 ++ .../kubernetes/utils/xcom_sidecar/index.html | 987 ++ .../kubernetes/example_kubernetes/index.html | 995 ++ .../example_kubernetes_async/index.html | 995 ++ .../example_kubernetes_decorator/index.html | 942 ++ .../example_kubernetes_job/index.html | 935 ++ .../example_kubernetes_resource/index.html | 938 ++ .../example_spark_kubernetes/index.html | 928 ++ .../providers/cncf/kubernetes/index.html | 904 ++ .../8.1.1/_images/arch-diag-kubernetes.png | Bin 0 -> 21804 bytes .../8.1.1/_images/arch-diag-kubernetes2.png | Bin 0 -> 86384 bytes .../8.1.1/_images/k8s-failed-pod.png | Bin 0 -> 18937 bytes .../8.1.1/_images/k8s-happy-path.png | Bin 0 -> 17257 bytes .../airflow/providers/cncf/kubernetes.html | 901 ++ .../providers/cncf/kubernetes/callbacks.html | 972 ++ .../kubernetes/decorators/kubernetes.html | 1013 ++ .../executors/kubernetes_executor.html | 1658 +++ .../executors/kubernetes_executor_types.html | 898 ++ .../executors/kubernetes_executor_utils.html | 1401 ++ .../executors/local_kubernetes_executor.html | 1108 ++ .../cncf/kubernetes/hooks/kubernetes.html | 1679 +++ .../providers/cncf/kubernetes/k8s_model.html | 923 ++ .../cncf/kubernetes/kube_client.html | 1008 ++ .../cncf/kubernetes/kube_config.html | 964 ++ .../kubernetes_helper_functions.html | 1062 ++ .../operators/custom_object_launcher.html | 1229 ++ .../cncf/kubernetes/operators/job.html | 1386 ++ .../cncf/kubernetes/operators/pod.html | 1993 +++ .../cncf/kubernetes/operators/resource.html | 1038 ++ .../operators/spark_kubernetes.html | 1169 ++ .../cncf/kubernetes/pod_generator.html | 1536 +++ .../kubernetes/pod_generator_deprecated.html | 1170 ++ .../kubernetes/pod_launcher_deprecated.html | 1181 ++ .../kubernetes/python_kubernetes_script.html | 953 ++ .../resource_convert/configmap.html | 913 ++ .../resource_convert/env_variable.html | 900 ++ .../kubernetes/resource_convert/secret.html | 901 ++ .../providers/cncf/kubernetes/secret.html | 986 ++ .../kubernetes/sensors/spark_kubernetes.html | 999 ++ .../cncf/kubernetes/template_rendering.html | 932 ++ .../cncf/kubernetes/triggers/job.html | 962 ++ .../cncf/kubernetes/triggers/pod.html | 1173 ++ .../cncf/kubernetes/utils/delete_from.html | 1015 ++ .../utils/k8s_resource_iterator.html | 907 ++ .../cncf/kubernetes/utils/pod_manager.html | 1684 +++ .../cncf/kubernetes/utils/xcom_sidecar.html | 927 ++ .../8.1.1/_modules/index.html | 896 ++ .../cncf/kubernetes/example_kubernetes.html | 1038 ++ .../kubernetes/example_kubernetes_async.html | 1069 ++ .../example_kubernetes_decorator.html | 928 ++ .../kubernetes/example_kubernetes_job.html | 965 ++ .../example_kubernetes_resource.html | 943 ++ .../kubernetes/example_spark_kubernetes.html | 947 ++ .../cncf/kubernetes/callbacks/index.rst.txt | 128 + .../cncf/kubernetes/decorators/index.rst.txt | 15 + .../decorators/kubernetes/index.rst.txt | 33 + .../cncf/kubernetes/executors/index.rst.txt | 18 + .../kubernetes_executor/index.rst.txt | 166 + .../kubernetes_executor_types/index.rst.txt | 28 + .../kubernetes_executor_utils/index.rst.txt | 144 + .../local_kubernetes_executor/index.rst.txt | 195 + .../cncf/kubernetes/hooks/index.rst.txt | 15 + .../kubernetes/hooks/kubernetes/index.rst.txt | 392 + .../providers/cncf/kubernetes/index.rst.txt | 51 + .../cncf/kubernetes/k8s_model/index.rst.txt | 66 + .../cncf/kubernetes/kube_client/index.rst.txt | 52 + .../cncf/kubernetes/kube_config/index.rst.txt | 40 + .../index.rst.txt | 6 + .../kubernetes_helper_functions/index.rst.txt | 79 + .../custom_object_launcher/index.rst.txt | 149 + .../cncf/kubernetes/operators/index.rst.txt | 20 + .../kubernetes/operators/job/index.rst.txt | 243 + .../operators/kubernetes_pod/index.rst.txt | 11 + .../kubernetes/operators/pod/index.rst.txt | 330 + .../operators/resource/index.rst.txt | 65 + .../operators/spark_kubernetes/index.rst.txt | 139 + .../kubernetes/pod_generator/index.rst.txt | 279 + .../pod_generator_deprecated/index.rst.txt | 176 + .../pod_launcher_deprecated/index.rst.txt | 131 + .../pod_template_file_examples/index.rst.txt | 6 + .../python_kubernetes_script/index.rst.txt | 44 + .../resource_convert/configmap/index.rst.txt | 36 + .../env_variable/index.rst.txt | 27 + .../kubernetes/resource_convert/index.rst.txt | 17 + .../resource_convert/secret/index.rst.txt | 36 + .../cncf/kubernetes/secret/index.rst.txt | 62 + .../cncf/kubernetes/sensors/index.rst.txt | 15 + .../sensors/spark_kubernetes/index.rst.txt | 64 + .../template_rendering/index.rst.txt | 30 + .../cncf/kubernetes/triggers/index.rst.txt | 17 + .../kubernetes/triggers/job/index.rst.txt | 50 + .../triggers/kubernetes_pod/index.rst.txt | 11 + .../kubernetes/triggers/pod/index.rst.txt | 107 + .../utils/delete_from/index.rst.txt | 51 + .../cncf/kubernetes/utils/index.rst.txt | 18 + .../utils/k8s_resource_iterator/index.rst.txt | 22 + .../utils/pod_manager/index.rst.txt | 333 + .../utils/xcom_sidecar/index.rst.txt | 70 + .../example_kubernetes/index.rst.txt | 79 + .../example_kubernetes_async/index.rst.txt | 79 + .../index.rst.txt | 34 + .../example_kubernetes_job/index.rst.txt | 41 + .../example_kubernetes_resource/index.rst.txt | 43 + .../example_spark_kubernetes/index.rst.txt | 37 + .../providers/cncf/kubernetes/index.rst.txt | 20 + .../8.1.1/_sources/changelog.rst.txt | 25 + .../8.1.1/_sources/cli-ref.rst.txt | 29 + .../8.1.1/_sources/commits.rst.txt | 1141 ++ .../8.1.1/_sources/configurations-ref.rst.txt | 18 + .../_sources/connections/kubernetes.rst.txt | 84 + .../8.1.1/_sources/index.rst.txt | 120 + .../installing-providers-from-sources.rst.txt | 18 + .../_sources/kubernetes_executor.rst.txt | 290 + .../local_kubernetes_executor.rst.txt | 37 + .../8.1.1/_sources/operators.rst.txt | 669 + .../8.1.1/_sources/security.rst.txt | 18 + ...e.1e8bd061cd6da7fc9cf755528e8ffc24.min.css | 1 + .../_sphinx_design_static/design-tabs.js | 27 + .../_static/_gen/css/main-custom.min.css | 1 + .../8.1.1/_static/_gen/css/main.min.css | 7 + .../8.1.1/_static/_gen/js/docs.js | 1 + .../_sphinx_javascript_frameworks_compat.js | 134 + .../8.1.1/_static/basic.css | 899 ++ .../8.1.1/_static/check-solid.svg | 4 + .../8.1.1/_static/clipboard.min.js | 7 + .../8.1.1/_static/copy-button.svg | 5 + .../8.1.1/_static/copybutton.css | 94 + .../8.1.1/_static/copybutton.js | 248 + .../8.1.1/_static/copybutton_funcs.js | 73 + .../8.1.1/_static/custom.css | 33 + ...e.1e8bd061cd6da7fc9cf755528e8ffc24.min.css | 1 + .../8.1.1/_static/design-tabs.js | 27 + .../8.1.1/_static/doctools.js | 156 + .../8.1.1/_static/documentation_options.js | 14 + .../8.1.1/_static/file.png | Bin 0 -> 286 bytes .../8.1.1/_static/graphviz.css | 19 + .../8.1.1/_static/jquery-3.6.0.js | 10881 ++++++++++++++++ .../8.1.1/_static/jquery.js | 2 + .../8.1.1/_static/js/globaltoc.js | 24 + .../8.1.1/_static/language_data.js | 199 + .../8.1.1/_static/minus.png | Bin 0 -> 90 bytes .../8.1.1/_static/pin_32.png | Bin 0 -> 1201 bytes .../8.1.1/_static/plus.png | Bin 0 -> 90 bytes .../8.1.1/_static/pygments.css | 75 + .../8.1.1/_static/searchtools.js | 566 + .../8.1.1/_static/sphinx_highlight.js | 144 + .../8.1.1/_static/underscore-1.13.1.js | 2042 +++ .../8.1.1/_static/underscore.js | 6 + .../8.1.1/changelog.html | 2394 ++++ .../8.1.1/cli-ref.html | 1012 ++ .../8.1.1/commits.html | 4211 ++++++ .../8.1.1/configurations-ref.html | 1409 ++ .../8.1.1/connections/index.html | 1 + .../8.1.1/connections/kubernetes.html | 943 ++ .../8.1.1/genindex.html | 2672 ++++ .../8.1.1/index.html | 960 ++ .../installing-providers-from-sources.html | 996 ++ .../8.1.1/kubernetes_executor.html | 1350 ++ .../8.1.1/local_kubernetes_executor.html | 903 ++ .../8.1.1/objects.inv | Bin 0 -> 7003 bytes .../8.1.1/operators.html | 1734 +++ ...e.1e8bd061cd6da7fc9cf755528e8ffc24.min.css | 1 + .../_sphinx_design_static/design-tabs.js | 27 + .../8.1.1/py-modindex.html | 1147 ++ .../8.1.1/search.html | 909 ++ .../8.1.1/searchindex.js | 1 + .../8.1.1/security.html | 907 ++ .../stable.txt | 2 +- .../6.3.0/.buildinfo | 4 + .../databricks/hooks/databricks/index.html | 1894 +++ .../hooks/databricks_base/index.html | 1108 ++ .../hooks/databricks_sql/index.html | 1034 ++ .../providers/databricks/hooks/index.html | 881 ++ .../airflow/providers/databricks/index.html | 913 ++ .../operators/databricks/index.html | 1559 +++ .../operators/databricks_repos/index.html | 1071 ++ .../operators/databricks_sql/index.html | 1072 ++ .../providers/databricks/operators/index.html | 881 ++ .../sensors/databricks_partition/index.html | 961 ++ .../sensors/databricks_sql/index.html | 967 ++ .../providers/databricks/sensors/index.html | 880 ++ .../databricks/triggers/databricks/index.html | 950 ++ .../providers/databricks/triggers/index.html | 879 ++ .../databricks/utils/databricks/index.html | 923 ++ .../providers/databricks/utils/index.html | 879 ++ .../databricks/example_databricks/index.html | 911 ++ .../example_databricks_repos/index.html | 906 ++ .../example_databricks_sensors/index.html | 900 ++ .../example_databricks_sql/index.html | 908 ++ .../system/providers/databricks/index.html | 880 ++ .../airflow/providers/databricks.html | 879 ++ .../databricks/hooks/databricks.html | 1518 +++ .../databricks/hooks/databricks_base.html | 1566 +++ .../databricks/hooks/databricks_sql.html | 1135 ++ .../databricks/operators/databricks.html | 1725 +++ .../operators/databricks_repos.html | 1136 ++ .../databricks/operators/databricks_sql.html | 1194 ++ .../sensors/databricks_partition.html | 1077 ++ .../databricks/sensors/databricks_sql.html | 977 ++ .../databricks/triggers/databricks.html | 943 ++ .../databricks/utils/databricks.html | 905 ++ .../6.3.0/_modules/index.html | 850 ++ .../databricks/example_databricks.html | 996 ++ .../databricks/example_databricks_repos.html | 927 ++ .../example_databricks_sensors.html | 939 ++ .../databricks/example_databricks_sql.html | 962 ++ .../databricks/hooks/databricks/index.rst.txt | 573 + .../hooks/databricks_base/index.rst.txt | 160 + .../hooks/databricks_sql/index.rst.txt | 114 + .../providers/databricks/hooks/index.rst.txt | 17 + .../providers/databricks/index.rst.txt | 27 + .../operators/databricks/index.rst.txt | 559 + .../operators/databricks_repos/index.rst.txt | 156 + .../operators/databricks_sql/index.rst.txt | 161 + .../databricks/operators/index.rst.txt | 17 + .../databricks_partition/index.rst.txt | 76 + .../sensors/databricks_sql/index.rst.txt | 78 + .../databricks/sensors/index.rst.txt | 16 + .../triggers/databricks/index.rst.txt | 61 + .../databricks/triggers/index.rst.txt | 15 + .../databricks/utils/databricks/index.rst.txt | 40 + .../providers/databricks/utils/index.rst.txt | 15 + .../example_databricks/index.rst.txt | 43 + .../example_databricks_repos/index.rst.txt | 31 + .../example_databricks_sensors/index.rst.txt | 27 + .../example_databricks_sql/index.rst.txt | 39 + .../system/providers/databricks/index.rst.txt | 18 + .../6.3.0/_sources/changelog.rst.txt | 25 + .../6.3.0/_sources/commits.rst.txt | 697 + .../_sources/connections/databricks.rst.txt | 110 + .../6.3.0/_sources/index.rst.txt | 136 + .../installing-providers-from-sources.rst.txt | 18 + .../_sources/operators/copy_into.rst.txt | 52 + .../6.3.0/_sources/operators/index.rst.txt | 28 + .../_sources/operators/jobs_create.rst.txt | 91 + .../_sources/operators/repos_create.rst.txt | 69 + .../_sources/operators/repos_delete.rst.txt | 61 + .../_sources/operators/repos_update.rst.txt | 66 + .../6.3.0/_sources/operators/run_now.rst.txt | 57 + .../6.3.0/_sources/operators/sql.rst.txt | 169 + .../_sources/operators/submit_run.rst.txt | 136 + .../6.3.0/_sources/security.rst.txt | 18 + ...e.1e8bd061cd6da7fc9cf755528e8ffc24.min.css | 1 + .../_sphinx_design_static/design-tabs.js | 27 + .../_static/_gen/css/main-custom.min.css | 1 + .../6.3.0/_static/_gen/css/main.min.css | 7 + .../6.3.0/_static/_gen/js/docs.js | 1 + .../_sphinx_javascript_frameworks_compat.js | 134 + .../6.3.0/_static/basic.css | 899 ++ .../6.3.0/_static/check-solid.svg | 4 + .../6.3.0/_static/clipboard.min.js | 7 + .../6.3.0/_static/copy-button.svg | 5 + .../6.3.0/_static/copybutton.css | 94 + .../6.3.0/_static/copybutton.js | 248 + .../6.3.0/_static/copybutton_funcs.js | 73 + .../6.3.0/_static/custom.css | 33 + ...e.1e8bd061cd6da7fc9cf755528e8ffc24.min.css | 1 + .../6.3.0/_static/design-tabs.js | 27 + .../6.3.0/_static/doctools.js | 156 + .../6.3.0/_static/documentation_options.js | 14 + .../6.3.0/_static/file.png | Bin 0 -> 286 bytes .../6.3.0/_static/graphviz.css | 19 + .../6.3.0/_static/jquery-3.6.0.js | 10881 ++++++++++++++++ .../6.3.0/_static/jquery.js | 2 + .../6.3.0/_static/js/globaltoc.js | 24 + .../6.3.0/_static/language_data.js | 199 + .../6.3.0/_static/minus.png | Bin 0 -> 90 bytes .../6.3.0/_static/pin_32.png | Bin 0 -> 1201 bytes .../6.3.0/_static/plus.png | Bin 0 -> 90 bytes .../6.3.0/_static/pygments.css | 75 + .../6.3.0/_static/searchtools.js | 566 + .../6.3.0/_static/sphinx_highlight.js | 144 + .../6.3.0/_static/underscore-1.13.1.js | 2042 +++ .../6.3.0/_static/underscore.js | 6 + .../6.3.0/changelog.html | 1654 +++ .../6.3.0/commits.html | 2813 ++++ .../6.3.0/connections/databricks.html | 954 ++ .../6.3.0/genindex.html | 1685 +++ .../6.3.0/index.html | 966 ++ .../installing-providers-from-sources.html | 974 ++ .../6.3.0/objects.inv | Bin 0 -> 2831 bytes .../6.3.0/operators/copy_into.html | 914 ++ .../6.3.0/operators/index.html | 884 ++ .../6.3.0/operators/jobs_create.html | 997 ++ .../6.3.0/operators/repos_create.html | 940 ++ .../6.3.0/operators/repos_delete.html | 927 ++ .../6.3.0/operators/repos_update.html | 934 ++ .../6.3.0/operators/run_now.html | 904 ++ .../6.3.0/operators/sql.html | 1074 ++ .../6.3.0/operators/submit_run.html | 1004 ++ ...e.1e8bd061cd6da7fc9cf755528e8ffc24.min.css | 1 + .../_sphinx_design_static/design-tabs.js | 27 + .../6.3.0/py-modindex.html | 970 ++ .../6.3.0/search.html | 887 ++ .../6.3.0/searchindex.js | 1 + .../6.3.0/security.html | 885 ++ .../stable.txt | 2 +- .../1.0.4/.buildinfo | 4 + .../api/auth/backend/basic_auth/index.html | 963 ++ .../auth_manager/api/auth/backend/index.html | 886 ++ .../api/auth/backend/kerberos_auth/index.html | 955 ++ .../fab/auth_manager/api/auth/index.html | 887 ++ .../providers/fab/auth_manager/api/index.html | 888 ++ .../fab/auth_manager/api_endpoints/index.html | 882 ++ .../role_and_permission_endpoint/index.html | 966 ++ .../api_endpoints/user_endpoint/index.html | 954 ++ .../cli_commands/definition/index.html | 1030 ++ .../fab/auth_manager/cli_commands/index.html | 885 ++ .../cli_commands/role_command/index.html | 966 ++ .../cli_commands/sync_perm_command/index.html | 905 ++ .../cli_commands/user_command/index.html | 1058 ++ .../cli_commands/utils/index.html | 905 ++ .../auth_manager/decorators/auth/index.html | 892 ++ .../fab/auth_manager/decorators/index.html | 881 ++ .../auth_manager/fab_auth_manager/index.html | 1185 ++ .../providers/fab/auth_manager/index.html | 929 ++ .../models/anonymous_user/index.html | 919 ++ .../fab/auth_manager/models/index.html | 1410 ++ .../fab/auth_manager/openapi/index.html | 870 ++ .../security_manager/constants/index.html | 886 ++ .../auth_manager/security_manager/index.html | 882 ++ .../security_manager/override/index.html | 2395 ++++ .../fab/auth_manager/views/index.html | 885 ++ .../auth_manager/views/permissions/index.html | 1101 ++ .../auth_manager/views/roles_list/index.html | 925 ++ .../fab/auth_manager/views/user/index.html | 1052 ++ .../auth_manager/views/user_edit/index.html | 993 ++ .../auth_manager/views/user_stats/index.html | 931 ++ .../_api/airflow/providers/fab/index.html | 931 ++ .../1.0.4/_images/add-role.png | Bin 0 -> 30509 bytes ..._fab_auth_manager_airflow_architecture.png | Bin 0 -> 81735 bytes .../1.0.4/_images/new-role.png | Bin 0 -> 14115 bytes .../1.0.4/_modules/airflow/providers/fab.html | 879 ++ .../api/auth/backend/basic_auth.html | 909 ++ .../api/auth/backend/kerberos_auth.html | 883 ++ .../role_and_permission_endpoint.html | 1009 ++ .../api_endpoints/user_endpoint.html | 1054 ++ .../auth_manager/cli_commands/definition.html | 1084 ++ .../cli_commands/role_command.html | 1071 ++ .../cli_commands/sync_perm_command.html | 878 ++ .../cli_commands/user_command.html | 1118 ++ .../fab/auth_manager/cli_commands/utils.html | 887 ++ .../fab/auth_manager/decorators/auth.html | 965 ++ .../fab/auth_manager/fab_auth_manager.html | 1350 ++ .../providers/fab/auth_manager/models.html | 1113 ++ .../auth_manager/models/anonymous_user.html | 891 ++ .../security_manager/constants.html | 865 ++ .../security_manager/override.html | 3604 +++++ .../fab/auth_manager/views/permissions.html | 929 ++ .../fab/auth_manager/views/roles_list.html | 881 ++ .../fab/auth_manager/views/user.html | 1027 ++ .../fab/auth_manager/views/user_edit.html | 899 ++ .../fab/auth_manager/views/user_stats.html | 872 ++ .../1.0.4/_modules/index.html | 856 ++ .../api/auth/backend/basic_auth/index.rst.txt | 59 + .../api/auth/backend/index.rst.txt | 16 + .../auth/backend/kerberos_auth/index.rst.txt | 50 + .../fab/auth_manager/api/auth/index.rst.txt | 15 + .../fab/auth_manager/api/index.rst.txt | 15 + .../auth_manager/api_endpoints/index.rst.txt | 16 + .../index.rst.txt | 54 + .../api_endpoints/user_endpoint/index.rst.txt | 48 + .../cli_commands/definition/index.rst.txt | 111 + .../auth_manager/cli_commands/index.rst.txt | 19 + .../cli_commands/role_command/index.rst.txt | 67 + .../sync_perm_command/index.rst.txt | 29 + .../cli_commands/user_command/index.rst.txt | 122 + .../cli_commands/utils/index.rst.txt | 22 + .../decorators/auth/index.rst.txt | 17 + .../fab/auth_manager/decorators/index.rst.txt | 15 + .../fab_auth_manager/index.rst.txt | 193 + .../providers/fab/auth_manager/index.rst.txt | 31 + .../models/anonymous_user/index.rst.txt | 33 + .../fab/auth_manager/models/index.rst.txt | 357 + .../fab/auth_manager/openapi/index.rst.txt | 6 + .../security_manager/constants/index.rst.txt | 13 + .../security_manager/index.rst.txt | 16 + .../security_manager/override/index.rst.txt | 981 ++ .../fab/auth_manager/views/index.rst.txt | 19 + .../views/permissions/index.rst.txt | 161 + .../views/roles_list/index.rst.txt | 39 + .../fab/auth_manager/views/user/index.rst.txt | 126 + .../views/user_edit/index.rst.txt | 86 + .../views/user_stats/index.rst.txt | 44 + .../_api/airflow/providers/fab/index.rst.txt | 23 + .../auth-manager/access-control.rst.txt | 332 + .../auth-manager/api-authentication.rst.txt | 137 + .../1.0.4/_sources/auth-manager/index.rst.txt | 32 + .../webserver-authentication.rst.txt | 231 + .../1.0.4/_sources/changelog.rst.txt | 25 + .../1.0.4/_sources/cli-ref.rst.txt | 29 + .../1.0.4/_sources/commits.rst.txt | 135 + .../1.0.4/_sources/configurations-ref.rst.txt | 18 + .../1.0.4/_sources/index.rst.txt | 107 + .../installing-providers-from-sources.rst.txt | 18 + .../1.0.4/_sources/security.rst.txt | 18 + .../_sources/stable-rest-api-ref.rst.txt | 23 + ...e.1e8bd061cd6da7fc9cf755528e8ffc24.min.css | 1 + .../_sphinx_design_static/design-tabs.js | 27 + .../_static/_gen/css/main-custom.min.css | 1 + .../1.0.4/_static/_gen/css/main.min.css | 7 + .../1.0.4/_static/_gen/js/docs.js | 1 + .../_sphinx_javascript_frameworks_compat.js | 134 + .../1.0.4/_static/basic.css | 899 ++ .../1.0.4/_static/check-solid.svg | 4 + .../1.0.4/_static/clipboard.min.js | 7 + .../1.0.4/_static/copy-button.svg | 5 + .../1.0.4/_static/copybutton.css | 94 + .../1.0.4/_static/copybutton.js | 248 + .../1.0.4/_static/copybutton_funcs.js | 73 + .../1.0.4/_static/custom.css | 33 + ...e.1e8bd061cd6da7fc9cf755528e8ffc24.min.css | 1 + .../1.0.4/_static/design-tabs.js | 27 + .../1.0.4/_static/doctools.js | 156 + .../1.0.4/_static/documentation_options.js | 14 + .../1.0.4/_static/file.png | Bin 0 -> 286 bytes .../1.0.4/_static/graphviz.css | 19 + .../1.0.4/_static/jquery-3.6.0.js | 10881 ++++++++++++++++ .../1.0.4/_static/jquery.js | 2 + .../1.0.4/_static/js/globaltoc.js | 24 + .../1.0.4/_static/language_data.js | 199 + .../1.0.4/_static/minus.png | Bin 0 -> 90 bytes .../1.0.4/_static/pin_32.png | Bin 0 -> 1201 bytes .../1.0.4/_static/plus.png | Bin 0 -> 90 bytes .../1.0.4/_static/pygments.css | 75 + .../1.0.4/_static/searchtools.js | 566 + .../1.0.4/_static/sphinx_highlight.js | 144 + .../1.0.4/_static/underscore-1.13.1.js | 2042 +++ .../1.0.4/_static/underscore.js | 6 + .../1.0.4/auth-manager/access-control.html | 1756 +++ .../auth-manager/api-authentication.html | 970 ++ .../1.0.4/auth-manager/index.html | 879 ++ .../webserver-authentication.html | 1067 ++ .../1.0.4/changelog.html | 910 ++ .../1.0.4/cli-ref.html | 1462 +++ .../1.0.4/commits.html | 1165 ++ .../1.0.4/configurations-ref.html | 921 ++ .../1.0.4/genindex.html | 2190 ++++ .../1.0.4/index.html | 928 ++ .../installing-providers-from-sources.html | 974 ++ .../1.0.4/objects.inv | Bin 0 -> 4583 bytes ...e.1e8bd061cd6da7fc9cf755528e8ffc24.min.css | 1 + .../_sphinx_design_static/design-tabs.js | 27 + .../1.0.4/py-modindex.html | 1010 ++ .../1.0.4/search.html | 887 ++ .../1.0.4/searchindex.js | 1 + .../1.0.4/security.html | 885 ++ .../1.0.4/stable-rest-api-ref.html | 870 ++ .../apache-airflow-providers-fab/stable.txt | 2 +- 493 files changed, 311928 insertions(+), 3 deletions(-) create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/.buildinfo create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/callbacks/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/decorators/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/decorators/kubernetes/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_types/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_utils/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/local_kubernetes_executor/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/hooks/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/hooks/kubernetes/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/k8s_model/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/kube_client/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/kube_config/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/kubernetes_executor_templates/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/kubernetes_helper_functions/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/custom_object_launcher/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/job/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/kubernetes_pod/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/pod/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/resource/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/spark_kubernetes/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/pod_generator/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/pod_generator_deprecated/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/pod_launcher_deprecated/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/pod_template_file_examples/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/python_kubernetes_script/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/resource_convert/configmap/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/resource_convert/env_variable/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/resource_convert/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/resource_convert/secret/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/secret/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/sensors/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/sensors/spark_kubernetes/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/template_rendering/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/triggers/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/triggers/job/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/triggers/kubernetes_pod/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/triggers/pod/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/delete_from/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/k8s_resource_iterator/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/pod_manager/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/xcom_sidecar/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_async/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_decorator/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_job/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_resource/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_spark_kubernetes/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_images/arch-diag-kubernetes.png create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_images/arch-diag-kubernetes2.png create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_images/k8s-failed-pod.png create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_images/k8s-happy-path.png create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/callbacks.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/decorators/kubernetes.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/executors/kubernetes_executor.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_types.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_utils.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/executors/local_kubernetes_executor.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/hooks/kubernetes.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/k8s_model.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/kube_client.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/kube_config.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/kubernetes_helper_functions.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/custom_object_launcher.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/job.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/pod.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/resource.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/spark_kubernetes.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/pod_generator.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/pod_generator_deprecated.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/pod_launcher_deprecated.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/python_kubernetes_script.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/resource_convert/configmap.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/resource_convert/env_variable.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/resource_convert/secret.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/secret.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/sensors/spark_kubernetes.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/template_rendering.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/triggers/job.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/triggers/pod.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/utils/delete_from.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/utils/k8s_resource_iterator.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/utils/pod_manager.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/utils/xcom_sidecar.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes_async.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes_decorator.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes_job.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes_resource.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_spark_kubernetes.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/callbacks/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/decorators/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/decorators/kubernetes/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_types/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_utils/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/local_kubernetes_executor/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/hooks/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/hooks/kubernetes/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/k8s_model/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/kube_client/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/kube_config/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/kubernetes_executor_templates/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/kubernetes_helper_functions/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/custom_object_launcher/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/job/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/kubernetes_pod/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/pod/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/resource/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/spark_kubernetes/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/pod_generator/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/pod_generator_deprecated/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/pod_launcher_deprecated/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/pod_template_file_examples/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/python_kubernetes_script/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/resource_convert/configmap/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/resource_convert/env_variable/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/resource_convert/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/resource_convert/secret/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/secret/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/sensors/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/sensors/spark_kubernetes/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/template_rendering/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/triggers/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/triggers/job/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/triggers/kubernetes_pod/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/triggers/pod/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/delete_from/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/k8s_resource_iterator/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/pod_manager/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/xcom_sidecar/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_async/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_decorator/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_job/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_resource/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_spark_kubernetes/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/changelog.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/cli-ref.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/commits.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/configurations-ref.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/connections/kubernetes.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/installing-providers-from-sources.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/kubernetes_executor.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/local_kubernetes_executor.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/operators.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/security.rst.txt create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sphinx_design_static/design-tabs.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/_gen/css/main-custom.min.css create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/_gen/css/main.min.css create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/_gen/js/docs.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/_sphinx_javascript_frameworks_compat.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/basic.css create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/check-solid.svg create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/clipboard.min.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/copy-button.svg create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/copybutton.css create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/copybutton.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/copybutton_funcs.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/custom.css create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/design-tabs.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/doctools.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/documentation_options.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/file.png create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/graphviz.css create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/jquery-3.6.0.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/jquery.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/js/globaltoc.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/language_data.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/minus.png create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/pin_32.png create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/plus.png create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/pygments.css create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/searchtools.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/sphinx_highlight.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/underscore-1.13.1.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/underscore.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/changelog.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/cli-ref.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/commits.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/configurations-ref.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/connections/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/connections/kubernetes.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/genindex.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/index.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/installing-providers-from-sources.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/kubernetes_executor.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/local_kubernetes_executor.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/objects.inv create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/operators.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/output-spelling-results-apache-airflow-providers-cncf-kubernetes/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/output-spelling-results-apache-airflow-providers-cncf-kubernetes/_sphinx_design_static/design-tabs.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/py-modindex.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/search.html create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/searchindex.js create mode 100644 docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/security.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/.buildinfo create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/hooks/databricks/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/hooks/databricks_base/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/hooks/databricks_sql/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/hooks/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/operators/databricks/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/operators/databricks_repos/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/operators/databricks_sql/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/operators/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/sensors/databricks_partition/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/sensors/databricks_sql/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/sensors/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/triggers/databricks/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/triggers/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/utils/databricks/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/utils/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/example_databricks/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/example_databricks_repos/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/example_databricks_sensors/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/example_databricks_sql/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/hooks/databricks.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/hooks/databricks_base.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/hooks/databricks_sql.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/operators/databricks.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/operators/databricks_repos.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/operators/databricks_sql.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/sensors/databricks_partition.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/sensors/databricks_sql.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/triggers/databricks.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/utils/databricks.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/tests/system/providers/databricks/example_databricks.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/tests/system/providers/databricks/example_databricks_repos.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/tests/system/providers/databricks/example_databricks_sensors.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/tests/system/providers/databricks/example_databricks_sql.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/hooks/databricks/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/hooks/databricks_base/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/hooks/databricks_sql/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/hooks/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/operators/databricks/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/operators/databricks_repos/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/operators/databricks_sql/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/operators/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/sensors/databricks_partition/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/sensors/databricks_sql/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/sensors/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/triggers/databricks/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/triggers/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/utils/databricks/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/utils/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/example_databricks/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/example_databricks_repos/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/example_databricks_sensors/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/example_databricks_sql/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/changelog.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/commits.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/connections/databricks.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/installing-providers-from-sources.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/copy_into.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/jobs_create.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/repos_create.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/repos_delete.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/repos_update.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/run_now.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/sql.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/submit_run.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/security.rst.txt create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_sphinx_design_static/design-tabs.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/_gen/css/main-custom.min.css create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/_gen/css/main.min.css create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/_gen/js/docs.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/_sphinx_javascript_frameworks_compat.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/basic.css create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/check-solid.svg create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/clipboard.min.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/copy-button.svg create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/copybutton.css create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/copybutton.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/copybutton_funcs.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/custom.css create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/design-tabs.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/doctools.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/documentation_options.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/file.png create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/graphviz.css create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/jquery-3.6.0.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/jquery.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/js/globaltoc.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/language_data.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/minus.png create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/pin_32.png create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/plus.png create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/pygments.css create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/searchtools.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/sphinx_highlight.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/underscore-1.13.1.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/_static/underscore.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/changelog.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/commits.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/connections/databricks.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/genindex.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/installing-providers-from-sources.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/objects.inv create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/operators/copy_into.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/operators/index.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/operators/jobs_create.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/operators/repos_create.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/operators/repos_delete.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/operators/repos_update.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/operators/run_now.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/operators/sql.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/operators/submit_run.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/output-spelling-results-apache-airflow-providers-databricks/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/output-spelling-results-apache-airflow-providers-databricks/_sphinx_design_static/design-tabs.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/py-modindex.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/search.html create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/searchindex.js create mode 100644 docs-archive/apache-airflow-providers-databricks/6.3.0/security.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/.buildinfo create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/auth/backend/basic_auth/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/auth/backend/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/auth/backend/kerberos_auth/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/auth/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api_endpoints/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api_endpoints/role_and_permission_endpoint/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api_endpoints/user_endpoint/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/definition/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/role_command/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/sync_perm_command/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/user_command/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/utils/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/decorators/auth/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/decorators/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/fab_auth_manager/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/models/anonymous_user/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/models/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/openapi/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/security_manager/constants/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/security_manager/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/security_manager/override/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/permissions/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/roles_list/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/user/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/user_edit/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/user_stats/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_images/add-role.png create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_images/diagram_fab_auth_manager_airflow_architecture.png create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_images/new-role.png create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/api/auth/backend/basic_auth.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/api/auth/backend/kerberos_auth.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/api_endpoints/role_and_permission_endpoint.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/api_endpoints/user_endpoint.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/definition.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/role_command.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/sync_perm_command.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/user_command.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/utils.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/decorators/auth.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/fab_auth_manager.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/models.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/models/anonymous_user.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/security_manager/constants.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/security_manager/override.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/permissions.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/roles_list.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/user.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/user_edit.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/user_stats.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_modules/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/auth/backend/basic_auth/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/auth/backend/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/auth/backend/kerberos_auth/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/auth/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api_endpoints/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api_endpoints/role_and_permission_endpoint/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api_endpoints/user_endpoint/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/definition/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/role_command/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/sync_perm_command/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/user_command/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/utils/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/decorators/auth/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/decorators/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/fab_auth_manager/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/models/anonymous_user/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/models/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/openapi/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/security_manager/constants/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/security_manager/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/security_manager/override/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/permissions/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/roles_list/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/user/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/user_edit/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/user_stats/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/auth-manager/access-control.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/auth-manager/api-authentication.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/auth-manager/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/auth-manager/webserver-authentication.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/changelog.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/cli-ref.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/commits.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/configurations-ref.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/index.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/installing-providers-from-sources.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/security.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sources/stable-rest-api-ref.rst.txt create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_sphinx_design_static/design-tabs.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/_gen/css/main-custom.min.css create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/_gen/css/main.min.css create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/_gen/js/docs.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/_sphinx_javascript_frameworks_compat.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/basic.css create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/check-solid.svg create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/clipboard.min.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/copy-button.svg create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/copybutton.css create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/copybutton.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/copybutton_funcs.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/custom.css create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/design-tabs.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/doctools.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/documentation_options.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/file.png create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/graphviz.css create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/jquery-3.6.0.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/jquery.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/js/globaltoc.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/language_data.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/minus.png create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/pin_32.png create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/plus.png create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/pygments.css create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/searchtools.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/sphinx_highlight.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/underscore-1.13.1.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/_static/underscore.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/auth-manager/access-control.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/auth-manager/api-authentication.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/auth-manager/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/auth-manager/webserver-authentication.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/changelog.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/cli-ref.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/commits.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/configurations-ref.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/genindex.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/index.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/installing-providers-from-sources.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/objects.inv create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/output-spelling-results-apache-airflow-providers-fab/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/output-spelling-results-apache-airflow-providers-fab/_sphinx_design_static/design-tabs.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/py-modindex.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/search.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/searchindex.js create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/security.html create mode 100644 docs-archive/apache-airflow-providers-fab/1.0.4/stable-rest-api-ref.html diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/.buildinfo b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/.buildinfo new file mode 100644 index 00000000000..e0a70b30fab --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 070f48de7b90eb55b36452e050719a6e +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/callbacks/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/callbacks/index.html new file mode 100644 index 00000000000..c4252584744 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/callbacks/index.html @@ -0,0 +1,1081 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.callbacks — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.callbacks

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + +

ExecutionMode

Enum class for execution mode.

KubernetesPodOperatorCallback

KubernetesPodOperator callbacks methods.

+
+
+

Attributes

+ ++++ + + + + + +

client_type

+
+
+airflow.providers.cncf.kubernetes.callbacks.client_type[source]
+
+ +
+
+class airflow.providers.cncf.kubernetes.callbacks.ExecutionMode[source]
+

Bases: str, enum.Enum

+

Enum class for execution mode.

+
+
+SYNC = 'sync'[source]
+
+ +
+
+ASYNC = 'async'[source]
+
+ +
+ +
+
+class airflow.providers.cncf.kubernetes.callbacks.KubernetesPodOperatorCallback[source]
+

KubernetesPodOperator callbacks methods.

+

Currently, the callbacks methods are not called in the async mode, this support will be added +in the future.

+
+
+static on_sync_client_creation(*, client, **kwargs)[source]
+

Invoke this callback after creating the sync client.

+
+
Parameters
+

client (kubernetes.client.CoreV1Api) – the created kubernetes.client.CoreV1Api client.

+
+
+
+ +
+
+static on_pod_creation(*, pod, client, mode, **kwargs)[source]
+

Invoke this callback after creating the pod.

+
+
Parameters
+
    +
  • pod (kubernetes.client.V1Pod) – the created pod.

  • +
  • client (client_type) – the Kubernetes client that can be used in the callback.

  • +
  • mode (str) – the current execution mode, it’s one of (sync, async).

  • +
+
+
+
+ +
+
+static on_pod_starting(*, pod, client, mode, **kwargs)[source]
+

Invoke this callback when the pod starts.

+
+
Parameters
+
    +
  • pod (kubernetes.client.V1Pod) – the started pod.

  • +
  • client (client_type) – the Kubernetes client that can be used in the callback.

  • +
  • mode (str) – the current execution mode, it’s one of (sync, async).

  • +
+
+
+
+ +
+
+static on_pod_completion(*, pod, client, mode, **kwargs)[source]
+

Invoke this callback when the pod completes.

+
+
Parameters
+
    +
  • pod (kubernetes.client.V1Pod) – the completed pod.

  • +
  • client (client_type) – the Kubernetes client that can be used in the callback.

  • +
  • mode (str) – the current execution mode, it’s one of (sync, async).

  • +
+
+
+
+ +
+
+static on_pod_cleanup(*, pod, client, mode, **kwargs)[source]
+

Invoke this callback after cleaning/deleting the pod.

+
+
Parameters
+
    +
  • pod (kubernetes.client.V1Pod) – the completed pod.

  • +
  • client (client_type) – the Kubernetes client that can be used in the callback.

  • +
  • mode (str) – the current execution mode, it’s one of (sync, async).

  • +
+
+
+
+ +
+
+static on_operator_resuming(*, pod, event, client, mode, **kwargs)[source]
+

Invoke this callback when resuming the KubernetesPodOperator from deferred state.

+
+
Parameters
+
    +
  • pod (kubernetes.client.V1Pod) – the current state of the pod.

  • +
  • event (dict) – the returned event from the Trigger.

  • +
  • client (client_type) – the Kubernetes client that can be used in the callback.

  • +
  • mode (str) – the current execution mode, it’s one of (sync, async).

  • +
+
+
+
+ +
+
+static progress_callback(*, line, client, mode, **kwargs)[source]
+

Invoke this callback to process pod container logs.

+
+
Parameters
+
    +
  • line (str) – the read line of log.

  • +
  • client (client_type) – the Kubernetes client that can be used in the callback.

  • +
  • mode (str) – the current execution mode, it’s one of (sync, async).

  • +
+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/decorators/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/decorators/index.html new file mode 100644 index 00000000000..646603067dd --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/decorators/index.html @@ -0,0 +1,901 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.decorators — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/decorators/kubernetes/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/decorators/kubernetes/index.html new file mode 100644 index 00000000000..ef3e42f5f58 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/decorators/kubernetes/index.html @@ -0,0 +1,937 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.decorators.kubernetes — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.decorators.kubernetes

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + +

kubernetes_task([python_callable, multiple_outputs])

Kubernetes operator decorator.

+
+
+airflow.providers.cncf.kubernetes.decorators.kubernetes.kubernetes_task(python_callable=None, multiple_outputs=None, **kwargs)[source]
+

Kubernetes operator decorator.

+

This wraps a function to be executed in K8s using KubernetesPodOperator. +Also accepts any argument that DockerOperator will via kwargs. Can be +reused in a single DAG.

+
+
Parameters
+
    +
  • python_callable (Callable | None) – Function to decorate

  • +
  • multiple_outputs (bool | None) – if set, function return value will be +unrolled to multiple XCom values. Dict will unroll to xcom values with +keys as XCom keys. Defaults to False.

  • +
+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/index.html new file mode 100644 index 00000000000..64a97b6374f --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/index.html @@ -0,0 +1,904 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.executors — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor/index.html new file mode 100644 index 00000000000..606e6dfd717 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor/index.html @@ -0,0 +1,1140 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.executors.kubernetes_executor — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.executors.kubernetes_executor

+

KubernetesExecutor.

+
+

See also

+

For more information on how the KubernetesExecutor works, take a look at the guide: +Kubernetes Executor

+
+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

KubernetesExecutor

Executor for Kubernetes.

+
+
+

Attributes

+ ++++ + + + + + + + + + + + + + + +

base_version

ARG_NAMESPACE

ARG_MIN_PENDING_MINUTES

KUBERNETES_COMMANDS

+
+
+airflow.providers.cncf.kubernetes.executors.kubernetes_executor.base_version[source]
+
+ +
+
+airflow.providers.cncf.kubernetes.executors.kubernetes_executor.ARG_NAMESPACE[source]
+
+ +
+
+airflow.providers.cncf.kubernetes.executors.kubernetes_executor.ARG_MIN_PENDING_MINUTES[source]
+
+ +
+
+airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KUBERNETES_COMMANDS = ()[source]
+
+ +
+
+class airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KubernetesExecutor[source]
+

Bases: airflow.executors.base_executor.BaseExecutor

+

Executor for Kubernetes.

+
+
+RUNNING_POD_LOG_LINES = 100[source]
+
+ +
+
+supports_ad_hoc_ti_run: bool = True[source]
+
+ +
+
+clear_not_launched_queued_tasks(session=NEW_SESSION)[source]
+

Clear tasks that were not yet launched, but were previously queued.

+

Tasks can end up in a “Queued” state when a rescheduled/deferred operator +comes back up for execution (with the same try_number) before the +pod of its previous incarnation has been fully removed (we think).

+

It’s also possible when an executor abruptly shuts down (leaving a non-empty +task_queue on that executor), but that scenario is handled via normal adoption.

+

This method checks each of our queued tasks to see if the corresponding pod +is around, and if not, and there’s no matching entry in our own +task_queue, marks it for re-execution.

+
+
+
+ +
+
+start()[source]
+

Start the executor.

+
+
+
+ +
+
+execute_async(key, command, queue=None, executor_config=None)[source]
+

Execute task asynchronously.

+
+
+
+ +
+
+sync()[source]
+

Synchronize task state.

+
+
+
+ +
+
+get_task_log(ti, try_number)[source]
+

Return the task logs.

+
+
Parameters
+
+
+
Returns
+

tuple of logs and messages

+
+
Return type
+

tuple[list[str], list[str]]

+
+
+
+ +
+
+try_adopt_task_instances(tis)[source]
+

Try to adopt running task instances that have been abandoned by a SchedulerJob dying.

+

Anything that is not adopted will be cleared by the scheduler (and then become eligible for +re-scheduling)

+
+
Returns
+

any TaskInstances that were unable to be adopted

+
+
Return type
+

Sequence[airflow.models.taskinstance.TaskInstance]

+
+
+
+ +
+
+cleanup_stuck_queued_tasks(tis)[source]
+

Handle remnants of tasks that were failed because they were stuck in queued.

+

Tasks can get stuck in queued. If such a task is detected, it will be marked +as UP_FOR_RETRY if the task instance has remaining retries or marked as FAILED +if it doesn’t.

+
+
Parameters
+

tis (list[airflow.models.taskinstance.TaskInstance]) – List of Task Instances to clean up

+
+
Returns
+

List of readable task instances for a warning message

+
+
Return type
+

list[str]

+
+
+
+ +
+
+adopt_launched_task(kube_client, pod, tis_to_flush_by_key)[source]
+

Patch existing pod so that the current KubernetesJobWatcher can monitor it via label selectors.

+
+
Parameters
+
    +
  • kube_client (kubernetes.client.CoreV1Api) – kubernetes client for speaking to kube API

  • +
  • pod (kubernetes.client.models.V1Pod) – V1Pod spec that we will patch with new label

  • +
  • tis_to_flush_by_key (dict[airflow.models.taskinstancekey.TaskInstanceKey, kubernetes.client.models.V1Pod]) – TIs that will be flushed if they aren’t adopted

  • +
+
+
+
+ +
+
+end()[source]
+

Shut down the executor.

+
+
+
+ +
+
+terminate()[source]
+

Terminate the executor is not doing anything.

+
+ +
+
+static get_cli_commands()[source]
+

Vends CLI commands to be included in Airflow CLI.

+

Override this method to expose commands via Airflow CLI to manage this executor. This can +be commands to setup/teardown the executor, inspect state, etc. +Make sure to choose unique names for those commands, to avoid collisions.

+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_types/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_types/index.html new file mode 100644 index 00000000000..9d45a02ea45 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_types/index.html @@ -0,0 +1,924 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types

+
+

Module Contents

+
+
+airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types.ADOPTED = 'adopted'[source]
+
+ +
+
+airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types.KubernetesJobType[source]
+
+ +
+
+airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types.ALL_NAMESPACES = 'ALL_NAMESPACES'[source]
+
+ +
+
+airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types.POD_EXECUTOR_DONE_KEY = 'airflow_executor_done'[source]
+
+ +
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_utils/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_utils/index.html new file mode 100644 index 00000000000..a8df7c1da83 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_utils/index.html @@ -0,0 +1,1133 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + + + + + + + +

Singleton

Metaclass that allows to implement singleton pattern.

ResourceVersion

Singleton for tracking resourceVersion from Kubernetes.

KubernetesJobWatcher

Watches for Kubernetes jobs.

AirflowKubernetesScheduler

Airflow Scheduler for Kubernetes.

+
+
+

Functions

+ ++++ + + + + + +

get_base_pod_from_template(pod_template_file, kube_config)

Get base pod from template.

+
+
+

Attributes

+ ++++ + + + + + +

T

+
+
+airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.T[source]
+
+ +
+
+class airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.Singleton[source]
+

Bases: type, Generic[T]

+

Metaclass that allows to implement singleton pattern.

+
+
+__call__(*args, **kwargs)[source]
+

Call self as a function.

+
+
+
+ +
+ +
+
+class airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.ResourceVersion[source]
+

Singleton for tracking resourceVersion from Kubernetes.

+
+
+resource_version: dict[str, str][source]
+
+ +
+ +
+
+class airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.KubernetesJobWatcher(namespace, watcher_queue, resource_version, scheduler_job_id, kube_config)[source]
+

Bases: multiprocessing.Process, airflow.utils.log.logging_mixin.LoggingMixin

+

Watches for Kubernetes jobs.

+
+
+
+
+run()[source]
+

Perform watching.

+
+
+
+ +
+
+process_error(event)[source]
+

Process error response.

+
+
+
+ +
+
+process_status(pod_name, namespace, status, annotations, resource_version, event)[source]
+
+
+
+ +
+ +
+
+class airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.AirflowKubernetesScheduler(kube_config, result_queue, kube_client, scheduler_job_id)[source]
+

Bases: airflow.utils.log.logging_mixin.LoggingMixin

+

Airflow Scheduler for Kubernetes.

+
+
+
+
+run_pod_async(pod, **kwargs)[source]
+

Run POD asynchronously.

+
+
+
+ +
+
+run_next(next_job)[source]
+

Receives the next job to run, builds the pod, and creates it.

+
+
+
+ +
+
+delete_pod(pod_name, namespace)[source]
+

Delete Pod from a namespace; does not raise if it does not exist.

+
+
+
+ +
+
+patch_pod_executor_done(*, pod_name, namespace)[source]
+

Add a “done” annotation to ensure we don’t continually adopt pods.

+
+
+
+ +
+
+sync()[source]
+

Check the status of all currently running kubernetes jobs.

+

If a job is completed, its status is placed in the result queue to be sent back to the scheduler.

+
+
+
+ +
+
+process_watcher_task(task)[source]
+

Process the task by watcher.

+
+
+
+ +
+
+terminate()[source]
+

Terminates the watcher.

+
+
+
+ +
+ +
+
+airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.get_base_pod_from_template(pod_template_file, kube_config)[source]
+

Get base pod from template.

+

Reads either the pod_template_file set in the executor_config or the base pod_template_file +set in the airflow.cfg to craft a “base pod” that will be used by the KubernetesExecutor

+
+
Parameters
+
    +
  • pod_template_file (str | None) – absolute path to a pod_template_file.yaml or None

  • +
  • kube_config (Any) – The KubeConfig class generated by airflow that contains all kube metadata

  • +
+
+
Returns
+

a V1Pod that can be used as the base pod for k8s tasks

+
+
Return type
+

kubernetes.client.models.V1Pod

+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/local_kubernetes_executor/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/local_kubernetes_executor/index.html new file mode 100644 index 00000000000..e4636646455 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/executors/local_kubernetes_executor/index.html @@ -0,0 +1,1183 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

LocalKubernetesExecutor

Chooses between LocalExecutor and KubernetesExecutor based on the queue defined on the task.

+
+
+class airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor(local_executor, kubernetes_executor)[source]
+

Bases: airflow.utils.log.logging_mixin.LoggingMixin

+

Chooses between LocalExecutor and KubernetesExecutor based on the queue defined on the task.

+

When the task’s queue is the value of kubernetes_queue in section [local_kubernetes_executor] +of the configuration (default value: kubernetes), KubernetesExecutor is selected to run the task, +otherwise, LocalExecutor is used.

+
+
+
+
+property queued_tasks: dict[airflow.models.taskinstance.TaskInstanceKey, airflow.executors.base_executor.QueuedTaskInstanceType][source]
+

Return queued tasks from local and kubernetes executor.

+
+
+
+ +
+
+property running: set[airflow.models.taskinstance.TaskInstanceKey][source]
+

Return running tasks from local and kubernetes executor.

+
+
+
+ +
+
+property job_id: str | None[source]
+

Inherited attribute from BaseExecutor.

+

Since this is not really an executor, but a wrapper of executors +we implemented it as property, so we can have custom setter.

+
+
+
+ +
+
+property slots_available: int[source]
+

Number of new tasks this executor instance can accept.

+
+
+
+ +
+
+supports_ad_hoc_ti_run: bool = True[source]
+
+ +
+
+supports_pickling: bool = False[source]
+
+ +
+
+supports_sentry: bool = False[source]
+
+ +
+
+is_local: bool = False[source]
+
+ +
+
+is_single_threaded: bool = False[source]
+
+ +
+
+is_production: bool = True[source]
+
+ +
+
+serve_logs: bool = True[source]
+
+ +
+
+change_sensor_mode_to_reschedule: bool = False[source]
+
+ +
+
+callback_sink: airflow.callbacks.base_callback_sink.BaseCallbackSink | None[source]
+
+ +
+
+KUBERNETES_QUEUE[source]
+
+ +
+
+start()[source]
+

Start local and kubernetes executor.

+
+
+
+ +
+
+queue_command(task_instance, command, priority=1, queue=None)[source]
+

Queues command via local or kubernetes executor.

+
+
+
+ +
+
+queue_task_instance(task_instance, mark_success=False, pickle_id=None, ignore_all_deps=False, ignore_depends_on_past=False, wait_for_past_depends_before_skipping=False, ignore_task_deps=False, ignore_ti_state=False, pool=None, cfg_path=None)[source]
+

Queues task instance via local or kubernetes executor.

+
+
+
+ +
+
+get_task_log(ti, try_number)[source]
+

Fetch task log from kubernetes executor.

+
+
+
+ +
+
+has_task(task_instance)[source]
+

Check if a task is either queued or running in either local or kubernetes executor.

+
+
Parameters
+

task_instance (airflow.models.taskinstance.TaskInstance) – TaskInstance

+
+
Returns
+

True if the task is known to this executor

+
+
Return type
+

bool

+
+
+
+ +
+
+heartbeat()[source]
+

Heartbeat sent to trigger new jobs in local and kubernetes executor.

+
+
+
+ +
+
+get_event_buffer(dag_ids=None)[source]
+

Return and flush the event buffer from local and kubernetes executor.

+
+
Parameters
+

dag_ids (list[str] | None) – dag_ids to return events for, if None returns all

+
+
Returns
+

a dict of events

+
+
Return type
+

dict[airflow.models.taskinstance.TaskInstanceKey, airflow.executors.base_executor.EventBufferValueType]

+
+
+
+ +
+
+try_adopt_task_instances(tis)[source]
+

Try to adopt running task instances that have been abandoned by a SchedulerJob dying.

+

Anything that is not adopted will be cleared by the scheduler (and then become eligible for +re-scheduling)

+
+
Returns
+

any TaskInstances that were unable to be adopted

+
+
Return type
+

Sequence[airflow.models.taskinstance.TaskInstance]

+
+
+
+ +
+
+cleanup_stuck_queued_tasks(tis)[source]
+
+
+
+ +
+
+end()[source]
+

End local and kubernetes executor.

+
+
+
+ +
+
+terminate()[source]
+

Terminate local and kubernetes executor.

+
+
+
+ +
+
+debug_dump()[source]
+

Debug dump; called in response to SIGUSR2 by the scheduler.

+
+
+
+ +
+
+send_callback(request)[source]
+

Send callback for execution.

+
+
Parameters
+

request (airflow.callbacks.callback_requests.CallbackRequest) – Callback request to be executed.

+
+
+
+ +
+
+static get_cli_commands()[source]
+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/hooks/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/hooks/index.html new file mode 100644 index 00000000000..0719951d6b7 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/hooks/index.html @@ -0,0 +1,901 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.hooks — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/hooks/kubernetes/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/hooks/kubernetes/index.html new file mode 100644 index 00000000000..cad1071b41a --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/hooks/kubernetes/index.html @@ -0,0 +1,1558 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.hooks.kubernetes — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.hooks.kubernetes

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + +

KubernetesHook

Creates Kubernetes API connection.

AsyncKubernetesHook

Hook to use Kubernetes SDK asynchronously.

+
+
+

Attributes

+ ++++ + + + + + + + + + + + +

LOADING_KUBE_CONFIG_FILE_RESOURCE

JOB_FINAL_STATUS_CONDITION_TYPES

JOB_STATUS_CONDITION_TYPES

+
+
+airflow.providers.cncf.kubernetes.hooks.kubernetes.LOADING_KUBE_CONFIG_FILE_RESOURCE = 'Loading Kubernetes configuration file kube_config from {}...'[source]
+
+ +
+
+airflow.providers.cncf.kubernetes.hooks.kubernetes.JOB_FINAL_STATUS_CONDITION_TYPES[source]
+
+ +
+
+airflow.providers.cncf.kubernetes.hooks.kubernetes.JOB_STATUS_CONDITION_TYPES[source]
+
+ +
+
+class airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook(conn_id=default_conn_name, client_configuration=None, cluster_context=None, config_file=None, in_cluster=None, disable_verify_ssl=None, disable_tcp_keepalive=None)[source]
+

Bases: airflow.hooks.base.BaseHook, airflow.providers.cncf.kubernetes.utils.pod_manager.PodOperatorHookProtocol

+

Creates Kubernetes API connection.

+
    +
  • use in cluster configuration by using extra field in_cluster in connection

  • +
  • use custom config by providing path to the file using extra field kube_config_path in connection

  • +
  • +
    use custom configuration by providing content of kubeconfig file via

    extra field kube_config in connection

    +
    +
    +
  • +
  • use default config by providing no extras

  • +
+

This hook check for configuration option in the above order. Once an option is present it will +use this configuration.

+
+

See also

+

For more information about Kubernetes connection: +Kubernetes cluster Connection

+
+
+
Parameters
+
    +
  • conn_id (str | None) – The kubernetes connection +to Kubernetes cluster.

  • +
  • client_configuration (kubernetes.client.Configuration | None) – Optional dictionary of client configuration params. +Passed on to kubernetes client.

  • +
  • cluster_context (str | None) – Optionally specify a context to use (e.g. if you have multiple +in your kubeconfig.

  • +
  • config_file (str | None) – Path to kubeconfig file.

  • +
  • in_cluster (bool | None) – Set to True if running from within a kubernetes cluster.

  • +
  • disable_verify_ssl (bool | None) – Set to True if SSL verification should be disabled.

  • +
  • disable_tcp_keepalive (bool | None) – Set to True if you want to disable keepalive logic.

  • +
+
+
+
+
+property is_in_cluster: bool[source]
+

Expose whether the hook is configured with load_incluster_config or not.

+
+
+
+ +
+
+conn_name_attr = 'kubernetes_conn_id'[source]
+
+ +
+
+default_conn_name = 'kubernetes_default'[source]
+
+ +
+
+conn_type = 'kubernetes'[source]
+
+ +
+
+hook_name = 'Kubernetes Cluster Connection'[source]
+
+ +
+
+DEFAULT_NAMESPACE = 'default'[source]
+
+ +
+
+classmethod get_connection_form_widgets()[source]
+

Return connection widgets to add to connection form.

+
+
+
+ +
+
+classmethod get_ui_field_behaviour()[source]
+

Return custom field behaviour.

+
+
+
+ +
+
+classmethod get_connection(conn_id)[source]
+

Return requested connection.

+

If missing and conn_id is “kubernetes_default”, will return empty connection so that hook will +default to cluster-derived credentials.

+
+
+
+ +
+
+conn_extras()[source]
+
+ +
+
+get_conn()[source]
+

Return kubernetes api session for use with requests.

+
+
+
+ +
+
+api_client()[source]
+

Cached Kubernetes API client.

+
+
+
+ +
+
+core_v1_client()[source]
+

Get authenticated client object.

+
+
+
+ +
+
+apps_v1_client()[source]
+
+
+
+ +
+
+custom_object_client()[source]
+
+
+
+ +
+
+batch_v1_client()[source]
+
+
+
+ +
+
+create_custom_object(group, version, plural, body, namespace=None)[source]
+

Create custom resource definition object in Kubernetes.

+
+
Parameters
+
    +
  • group (str) – api group

  • +
  • version (str) – api version

  • +
  • plural (str) – api plural

  • +
  • body (str | dict) – crd object definition

  • +
  • namespace (str | None) – kubernetes namespace

  • +
+
+
+
+ +
+
+get_custom_object(group, version, plural, name, namespace=None)[source]
+

Get custom resource definition object from Kubernetes.

+
+
Parameters
+
    +
  • group (str) – api group

  • +
  • version (str) – api version

  • +
  • plural (str) – api plural

  • +
  • name (str) – crd object name

  • +
  • namespace (str | None) – kubernetes namespace

  • +
+
+
+
+ +
+
+delete_custom_object(group, version, plural, name, namespace=None, **kwargs)[source]
+

Delete custom resource definition object from Kubernetes.

+
+
Parameters
+
    +
  • group (str) – api group

  • +
  • version (str) – api version

  • +
  • plural (str) – api plural

  • +
  • name (str) – crd object name

  • +
  • namespace (str | None) – kubernetes namespace

  • +
+
+
+
+ +
+
+get_namespace()[source]
+

Return the namespace that defined in the connection.

+
+
+
+ +
+
+get_xcom_sidecar_container_image()[source]
+

Return the xcom sidecar image that defined in the connection.

+
+ +
+
+get_xcom_sidecar_container_resources()[source]
+

Return the xcom sidecar resources that defined in the connection.

+
+ +
+
+get_pod_log_stream(pod_name, container='', namespace=None)[source]
+

Retrieve a log stream for a container in a kubernetes pod.

+
+
Parameters
+
    +
  • pod_name (str) – pod name

  • +
  • container (str | None) – container name

  • +
  • namespace (str | None) – kubernetes namespace

  • +
+
+
+
+ +
+
+get_pod_logs(pod_name, container='', namespace=None)[source]
+

Retrieve a container’s log from the specified pod.

+
+
Parameters
+
    +
  • pod_name (str) – pod name

  • +
  • container (str | None) – container name

  • +
  • namespace (str | None) – kubernetes namespace

  • +
+
+
+
+ +
+
+get_pod(name, namespace)[source]
+

Read pod object from kubernetes API.

+
+
+
+ +
+
+get_namespaced_pod_list(label_selector='', namespace=None, watch=False, **kwargs)[source]
+

Retrieve a list of Kind pod which belong default kubernetes namespace.

+
+
Parameters
+
    +
  • label_selector (str | None) – A selector to restrict the list of returned objects by their labels

  • +
  • namespace (str | None) – kubernetes namespace

  • +
  • watch (bool) – Watch for changes to the described resources and return them as a stream

  • +
+
+
+
+ +
+
+get_deployment_status(name, namespace='default', **kwargs)[source]
+

Get status of existing Deployment.

+
+
Parameters
+
    +
  • name (str) – Name of Deployment to retrieve

  • +
  • namespace (str) – Deployment namespace

  • +
+
+
+
+ +
+
+create_job(job, **kwargs)[source]
+

Run Job.

+
+
Parameters
+

job (kubernetes.client.models.V1Job) – A kubernetes Job object

+
+
+
+ +
+
+get_job(job_name, namespace)[source]
+

Get Job of specified name and namespace.

+
+
Parameters
+
    +
  • job_name (str) – Name of Job to fetch.

  • +
  • namespace (str) – Namespace of the Job.

  • +
+
+
Returns
+

Job object

+
+
Return type
+

kubernetes.client.models.V1Job

+
+
+
+ +
+
+get_job_status(job_name, namespace)[source]
+

Get job with status of specified name and namespace.

+
+
Parameters
+
    +
  • job_name (str) – Name of Job to fetch.

  • +
  • namespace (str) – Namespace of the Job.

  • +
+
+
Returns
+

Job object

+
+
Return type
+

kubernetes.client.models.V1Job

+
+
+
+ +
+
+wait_until_job_complete(job_name, namespace, job_poll_interval=10)[source]
+

Block job of specified name and namespace until it is complete or failed.

+
+
Parameters
+
    +
  • job_name (str) – Name of Job to fetch.

  • +
  • namespace (str) – Namespace of the Job.

  • +
  • job_poll_interval (float) – Interval in seconds between polling the job status

  • +
+
+
Returns
+

Job object

+
+
Return type
+

kubernetes.client.models.V1Job

+
+
+
+ +
+
+list_jobs_all_namespaces()[source]
+

Get list of Jobs from all namespaces.

+
+
Returns
+

V1JobList object

+
+
Return type
+

kubernetes.client.V1JobList

+
+
+
+ +
+
+list_jobs_from_namespace(namespace)[source]
+

Get list of Jobs from dedicated namespace.

+
+
Parameters
+

namespace (str) – Namespace of the Job.

+
+
Returns
+

V1JobList object

+
+
Return type
+

kubernetes.client.V1JobList

+
+
+
+ +
+
+is_job_complete(job)[source]
+

Check whether the given job is complete (with success or fail).

+
+
Returns
+

Boolean indicating that the given job is complete.

+
+
Return type
+

bool

+
+
+
+ +
+
+static is_job_failed(job)[source]
+

Check whether the given job is failed.

+
+
Returns
+

Error message if the job is failed, and False otherwise.

+
+
Return type
+

str | bool

+
+
+
+ +
+
+static is_job_successful(job)[source]
+

Check whether the given job is completed successfully..

+
+
Returns
+

Error message if the job is failed, and False otherwise.

+
+
Return type
+

str | bool

+
+
+
+ +
+
+patch_namespaced_job(job_name, namespace, body)[source]
+

Update the specified Job.

+
+
Parameters
+
    +
  • job_name (str) – name of the Job

  • +
  • namespace (str) – the namespace to run within kubernetes

  • +
  • body (object) – json object with parameters for update

  • +
+
+
+
+ +
+ +
+
+class airflow.providers.cncf.kubernetes.hooks.kubernetes.AsyncKubernetesHook(*args, **kwargs)[source]
+

Bases: KubernetesHook

+

Hook to use Kubernetes SDK asynchronously.

+
+
+async get_conn_extras()[source]
+
+
+
+ +
+
+async get_conn()[source]
+
+
+
+ +
+
+async get_pod(name, namespace)[source]
+

Get pod’s object.

+
+
Parameters
+
    +
  • name (str) – Name of the pod.

  • +
  • namespace (str) – Name of the pod’s namespace.

  • +
+
+
+
+ +
+
+async delete_pod(name, namespace)[source]
+

Delete pod’s object.

+
+
Parameters
+
    +
  • name (str) – Name of the pod.

  • +
  • namespace (str) – Name of the pod’s namespace.

  • +
+
+
+
+ +
+
+async read_logs(name, namespace)[source]
+

Read logs inside the pod while starting containers inside.

+

All the logs will be outputted with its timestamp to track +the logs after the execution of the pod is completed. The +method is used for async output of the logs only in the pod +failed it execution or the task was cancelled by the user.

+
+
Parameters
+
    +
  • name (str) – Name of the pod.

  • +
  • namespace (str) – Name of the pod’s namespace.

  • +
+
+
+
+ +
+
+async get_job_status(name, namespace)[source]
+

Get job’s status object.

+
+
Parameters
+
    +
  • name (str) – Name of the pod.

  • +
  • namespace (str) – Name of the pod’s namespace.

  • +
+
+
+
+ +
+
+async wait_until_job_complete(name, namespace, poll_interval=10)[source]
+

Block job of specified name and namespace until it is complete or failed.

+
+
Parameters
+
    +
  • name (str) – Name of Job to fetch.

  • +
  • namespace (str) – Namespace of the Job.

  • +
  • poll_interval (float) – Interval in seconds between polling the job status

  • +
+
+
Returns
+

Job object

+
+
Return type
+

kubernetes.client.models.V1Job

+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/index.html new file mode 100644 index 00000000000..1f868203bc2 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/index.html @@ -0,0 +1,978 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes

+
+

Subpackages

+
+ +
+
+ +
+

Package Contents

+
+
+airflow.providers.cncf.kubernetes.__version__ = '8.1.1'[source]
+
+ +
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/k8s_model/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/k8s_model/index.html new file mode 100644 index 00000000000..6a5ea9a5bb4 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/k8s_model/index.html @@ -0,0 +1,984 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.k8s_model — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.k8s_model

+

Classes for interacting with Kubernetes API.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

K8SModel

Airflow Kubernetes models are here for backwards compatibility reasons only.

+
+
+

Functions

+ ++++ + + + + + +

append_to_pod(pod, k8s_objects)

Attach additional specs to an existing pod object.

+
+
+class airflow.providers.cncf.kubernetes.k8s_model.K8SModel[source]
+

Bases: abc.ABC

+

Airflow Kubernetes models are here for backwards compatibility reasons only.

+

Ideally clients should use the kubernetes API +and the process of

+
+

client input -> Airflow k8s models -> k8s models

+
+

can be avoided. All of these models implement the +attach_to_pod method so that they integrate with the kubernetes client.

+
+
+abstract attach_to_pod(pod)[source]
+

Attaches to pod.

+
+
Parameters
+

pod (kubernetes.client.models.V1Pod) – A pod to attach this Kubernetes object to

+
+
Returns
+

The pod with the object attached

+
+
Return type
+

kubernetes.client.models.V1Pod

+
+
+
+ +
+ +
+
+airflow.providers.cncf.kubernetes.k8s_model.append_to_pod(pod, k8s_objects)[source]
+

Attach additional specs to an existing pod object.

+
+
Parameters
+
    +
  • pod (kubernetes.client.models.V1Pod) – A pod to attach a list of Kubernetes objects to

  • +
  • k8s_objects (list[K8SModel] | None) – a potential None list of K8SModels

  • +
+
+
Returns
+

pod with the objects attached if they exist

+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/kube_client/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/kube_client/index.html new file mode 100644 index 00000000000..146d017e85f --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/kube_client/index.html @@ -0,0 +1,968 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.kube_client — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.kube_client

+

Client for kubernetes communication.

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + +

get_kube_client([in_cluster, cluster_context, config_file])

Retrieve Kubernetes client.

+
+
+

Attributes

+ ++++ + + + + + + + + +

log

has_kubernetes

+
+
+airflow.providers.cncf.kubernetes.kube_client.log[source]
+
+ +
+
+airflow.providers.cncf.kubernetes.kube_client.has_kubernetes = True[source]
+
+ +
+
+airflow.providers.cncf.kubernetes.kube_client.get_kube_client(in_cluster=None, cluster_context=None, config_file=None)[source]
+

Retrieve Kubernetes client.

+
+
Parameters
+
    +
  • in_cluster (bool | None) – whether we are in cluster

  • +
  • cluster_context (str | None) – context of the cluster

  • +
  • config_file (str | None) – configuration file

  • +
+
+
Returns
+

kubernetes client

+
+
Return type
+

kubernetes.client.CoreV1Api

+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/kube_config/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/kube_config/index.html new file mode 100644 index 00000000000..5a82349ae3f --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/kube_config/index.html @@ -0,0 +1,942 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.kube_config — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.kube_config

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

KubeConfig

Configuration for Kubernetes.

+
+
+class airflow.providers.cncf.kubernetes.kube_config.KubeConfig[source]
+

Configuration for Kubernetes.

+
+
+core_section = 'core'[source]
+
+ +
+
+kubernetes_section = 'kubernetes_executor'[source]
+
+ +
+
+logging_section = 'logging'[source]
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/kubernetes_executor_templates/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/kubernetes_executor_templates/index.html new file mode 100644 index 00000000000..60e7c35433a --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/kubernetes_executor_templates/index.html @@ -0,0 +1,890 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.kubernetes_executor_templates — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/kubernetes_helper_functions/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/kubernetes_helper_functions/index.html new file mode 100644 index 00000000000..9c680382577 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/kubernetes_helper_functions/index.html @@ -0,0 +1,1035 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.kubernetes_helper_functions — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.kubernetes_helper_functions

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + + + + + + + + + + + + + +

create_unique_id([dag_id, task_id, max_length, unique])

Generate unique pod or job ID given a dag_id and / or task_id.

create_pod_id([dag_id, task_id, max_length, unique])

Generate unique pod ID given a dag_id and / or task_id.

annotations_to_key(annotations)

Build a TaskInstanceKey based on pod annotations.

get_logs_task_metadata()

annotations_for_logging_task_metadata(annotation_set)

+
+
+

Attributes

+ ++++ + + + + + + + + + + + +

log

alphanum_lower

POD_NAME_MAX_LENGTH

+
+
+airflow.providers.cncf.kubernetes.kubernetes_helper_functions.log[source]
+
+ +
+
+airflow.providers.cncf.kubernetes.kubernetes_helper_functions.alphanum_lower[source]
+
+ +
+
+airflow.providers.cncf.kubernetes.kubernetes_helper_functions.POD_NAME_MAX_LENGTH = 63[source]
+
+ +
+
+airflow.providers.cncf.kubernetes.kubernetes_helper_functions.create_unique_id(dag_id=None, task_id=None, *, max_length=POD_NAME_MAX_LENGTH, unique=True)[source]
+

Generate unique pod or job ID given a dag_id and / or task_id.

+
+
Parameters
+
    +
  • dag_id (str | None) – DAG ID

  • +
  • task_id (str | None) – Task ID

  • +
  • max_length (int) – max number of characters

  • +
  • unique (bool) – whether a random string suffix should be added

  • +
+
+
Returns
+

A valid identifier for a kubernetes pod name

+
+
Return type
+

str

+
+
+
+ +
+
+airflow.providers.cncf.kubernetes.kubernetes_helper_functions.create_pod_id(dag_id=None, task_id=None, *, max_length=POD_NAME_MAX_LENGTH, unique=True)[source]
+

Generate unique pod ID given a dag_id and / or task_id.

+
+
Parameters
+
    +
  • dag_id (str | None) – DAG ID

  • +
  • task_id (str | None) – Task ID

  • +
  • max_length (int) – max number of characters

  • +
  • unique (bool) – whether a random string suffix should be added

  • +
+
+
Returns
+

A valid identifier for a kubernetes pod name

+
+
Return type
+

str

+
+
+
+ +
+
+airflow.providers.cncf.kubernetes.kubernetes_helper_functions.annotations_to_key(annotations)[source]
+

Build a TaskInstanceKey based on pod annotations.

+
+
+
+ +
+
+airflow.providers.cncf.kubernetes.kubernetes_helper_functions.get_logs_task_metadata()[source]
+
+
+
+ +
+
+airflow.providers.cncf.kubernetes.kubernetes_helper_functions.annotations_for_logging_task_metadata(annotation_set)[source]
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/custom_object_launcher/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/custom_object_launcher/index.html new file mode 100644 index 00000000000..1d717b24e90 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/custom_object_launcher/index.html @@ -0,0 +1,1126 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.operators.custom_object_launcher — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.operators.custom_object_launcher

+

Launches Custom object.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + + + + + + + + + + +

SparkJobSpec

Spark job spec.

KubernetesSpec

Spark kubernetes spec.

SparkResources

spark resources.

CustomObjectStatus

Status of the PODs.

CustomObjectLauncher

Launches PODS.

+
+
+

Functions

+ ++++ + + + + + +

should_retry_start_spark_job(exception)

Check if an Exception indicates a transient error and warrants retrying.

+
+
+airflow.providers.cncf.kubernetes.operators.custom_object_launcher.should_retry_start_spark_job(exception)[source]
+

Check if an Exception indicates a transient error and warrants retrying.

+
+
+
+ +
+
+class airflow.providers.cncf.kubernetes.operators.custom_object_launcher.SparkJobSpec(**entries)[source]
+

Spark job spec.

+
+
+validate()[source]
+
+ +
+
+update_resources()[source]
+
+ +
+ +
+
+class airflow.providers.cncf.kubernetes.operators.custom_object_launcher.KubernetesSpec(**entries)[source]
+

Spark kubernetes spec.

+
+
+set_attribute()[source]
+
+ +
+ +
+
+class airflow.providers.cncf.kubernetes.operators.custom_object_launcher.SparkResources(driver=None, executor=None)[source]
+

spark resources.

+
+
+
+
+property resources[source]
+

Return job resources.

+
+ +
+
+property driver_resources[source]
+

Return resources to use.

+
+ +
+
+property executor_resources[source]
+

Return resources to use.

+
+ +
+
+convert_resources()[source]
+
+ +
+ +
+
+class airflow.providers.cncf.kubernetes.operators.custom_object_launcher.CustomObjectStatus[source]
+

Status of the PODs.

+
+
+SUBMITTED = 'SUBMITTED'[source]
+
+ +
+
+RUNNING = 'RUNNING'[source]
+
+ +
+
+FAILED = 'FAILED'[source]
+
+ +
+
+SUCCEEDED = 'SUCCEEDED'[source]
+
+ +
+ +
+
+class airflow.providers.cncf.kubernetes.operators.custom_object_launcher.CustomObjectLauncher(name, namespace, kube_client, custom_obj_api, template_body=None)[source]
+

Bases: airflow.utils.log.logging_mixin.LoggingMixin

+

Launches PODS.

+
+
+
+
+pod_manager()[source]
+
+
+
+ +
+
+get_body()[source]
+
+ +
+
+start_spark_job(image=None, code_path=None, startup_timeout=600)[source]
+

Launch the pod synchronously and waits for completion.

+
+
Parameters
+
    +
  • image – image name

  • +
  • code_path – path to the .py file for python and jar file for scala

  • +
  • startup_timeout (int) – Timeout for startup of the pod (if pod is pending for too long, fails task)

  • +
+
+
Returns
+

+
+
+
+ +
+
+spark_job_not_running(spark_obj_spec)[source]
+

Test if spark_obj_spec has not started.

+
+ +
+
+check_pod_start_failure()[source]
+
+ +
+
+delete_spark_job(spark_job_name=None)[source]
+

Delete spark job.

+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/index.html new file mode 100644 index 00000000000..49b27d277e1 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/index.html @@ -0,0 +1,906 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.operators — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/job/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/job/index.html new file mode 100644 index 00000000000..241c9d56573 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/job/index.html @@ -0,0 +1,1257 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.operators.job — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.operators.job

+

Executes a Kubernetes Job.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + + + + +

KubernetesJobOperator

Executes a Kubernetes Job.

KubernetesDeleteJobOperator

Delete a Kubernetes Job.

KubernetesPatchJobOperator

Update a Kubernetes Job.

+
+
+

Attributes

+ ++++ + + + + + +

log

+
+
+airflow.providers.cncf.kubernetes.operators.job.log[source]
+
+ +
+
+class airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator(*, job_template_file=None, full_job_spec=None, backoff_limit=None, completion_mode=None, completions=None, manual_selector=None, parallelism=None, selector=None, suspend=None, ttl_seconds_after_finished=None, wait_until_job_complete=False, job_poll_interval=10, deferrable=conf.getboolean('operators', 'default_deferrable', fallback=False), **kwargs)[source]
+

Bases: airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator

+

Executes a Kubernetes Job.

+
+

See also

+

For more information on how to use this operator, take a look at the guide: +KubernetesJobOperator

+
+
+

Note

+

If you use Google Kubernetes Engine +and Airflow is not running in the same cluster, consider using +GKEStartJobOperator, which +simplifies the authorization process.

+
+
+
Parameters
+
    +
  • job_template_file (str | None) – path to job template file (templated)

  • +
  • full_job_spec (kubernetes.client.models.V1Job | None) – The complete JodSpec

  • +
  • backoff_limit (int | None) – Specifies the number of retries before marking this job failed. Defaults to 6

  • +
  • completion_mode (str | None) – CompletionMode specifies how Pod completions are tracked. It can be NonIndexed (default) or Indexed.

  • +
  • completions (int | None) – Specifies the desired number of successfully finished pods the job should be run with.

  • +
  • manual_selector (bool | None) – manualSelector controls generation of pod labels and pod selectors.

  • +
  • parallelism (int | None) – Specifies the maximum desired number of pods the job should run at any given time.

  • +
  • selector (kubernetes.client.models.V1LabelSelector | None) – The selector of this V1JobSpec.

  • +
  • suspend (bool | None) – Suspend specifies whether the Job controller should create Pods or not.

  • +
  • ttl_seconds_after_finished (int | None) – ttlSecondsAfterFinished limits the lifetime of a Job that has finished execution (either Complete or Failed).

  • +
  • wait_until_job_complete (bool) – Whether to wait until started job finished execution (either Complete or +Failed). Default is False.

  • +
  • job_poll_interval (float) – Interval in seconds between polling the job status. Default is 10. +Used if the parameter wait_until_job_complete set True.

  • +
  • deferrable (bool) – Run operator in the deferrable mode. Note that the parameter +wait_until_job_complete must be set True.

  • +
+
+
+
+
+template_fields: Sequence[str][source]
+
+ +
+
+hook()[source]
+
+
+
+ +
+
+client()[source]
+
+
+
+ +
+
+create_job(job_request_obj)[source]
+
+
+
+ +
+
+execute(context)[source]
+

Based on the deferrable parameter runs the pod asynchronously or synchronously.

+
+
+
+ +
+
+execute_deferrable()[source]
+
+ +
+
+execute_complete(context, event, **kwargs)[source]
+
+
+
+ +
+
+static deserialize_job_template_file(path)[source]
+

Generate a Job from a file.

+

Unfortunately we need access to the private method +_ApiClient__deserialize_model from the kubernetes client. +This issue is tracked here: https://github.com/kubernetes-client/python/issues/977.

+
+
Parameters
+

path (str) – Path to the file

+
+
Returns
+

a kubernetes.client.models.V1Job

+
+
Return type
+

kubernetes.client.models.V1Job

+
+
+
+ +
+
+on_kill()[source]
+

Override this method to clean up subprocesses when a task instance gets killed.

+

Any use of the threading, subprocess or multiprocessing module within an +operator needs to be cleaned up, or it will leave ghost processes behind.

+
+
+
+ +
+
+build_job_request_obj(context=None)[source]
+

Return V1Job object based on job template file, full job spec, and other operator parameters.

+

The V1Job attributes are derived (in order of precedence) from operator params, full job spec, job +template file.

+
+
+
+ +
+
+static reconcile_jobs(base_job, client_job)[source]
+

Merge Kubernetes Job objects.

+
+
Parameters
+
    +
  • base_job (kubernetes.client.models.V1Job) – has the base attributes which are overwritten if they exist +in the client job and remain if they do not exist in the client_job

  • +
  • client_job (kubernetes.client.models.V1Job | None) – the job that the client wants to create.

  • +
+
+
Returns
+

the merged jobs

+
+
Return type
+

kubernetes.client.models.V1Job

+
+
+

This can’t be done recursively as certain fields are overwritten and some are concatenated.

+
+ +
+
+static reconcile_job_specs(base_spec, client_spec)[source]
+

Merge Kubernetes JobSpec objects.

+
+
Parameters
+
    +
  • base_spec (kubernetes.client.models.V1JobSpec | None) – has the base attributes which are overwritten if they exist +in the client_spec and remain if they do not exist in the client_spec

  • +
  • client_spec (kubernetes.client.models.V1JobSpec | None) – the spec that the client wants to create.

  • +
+
+
Returns
+

the merged specs

+
+
Return type
+

kubernetes.client.models.V1JobSpec | None

+
+
+
+ +
+ +
+
+class airflow.providers.cncf.kubernetes.operators.job.KubernetesDeleteJobOperator(*, name, namespace, kubernetes_conn_id=KubernetesHook.default_conn_name, config_file=None, in_cluster=None, cluster_context=None, delete_on_status=None, wait_for_completion=False, poll_interval=10.0, **kwargs)[source]
+

Bases: airflow.models.BaseOperator

+

Delete a Kubernetes Job.

+
+

See also

+

For more information on how to use this operator, take a look at the guide: +KubernetesDeleteJobOperator

+
+
+
Parameters
+
    +
  • name (str) – name of the Job.

  • +
  • namespace (str) – the namespace to run within kubernetes.

  • +
  • kubernetes_conn_id (str | None) – The kubernetes connection id +for the Kubernetes cluster.

  • +
  • config_file (str | None) – The path to the Kubernetes config file. (templated) +If not specified, default value is ~/.kube/config

  • +
  • in_cluster (bool | None) – run kubernetes client with in_cluster configuration.

  • +
  • cluster_context (str | None) – context that points to kubernetes cluster. +Ignored when in_cluster is True. If None, current-context is used. (templated)

  • +
  • delete_on_status (str | None) – Condition for performing delete operation depending on the job status. Values: +None - delete the job regardless of its status, “Complete” - delete only successfully completed +jobs, “Failed” - delete only failed jobs. (default: None)

  • +
  • wait_for_completion (bool) – Whether to wait for the job to complete. (default: False)

  • +
  • poll_interval (float) – Interval in seconds between polling the job status. Used when the delete_on_status +parameter is set. (default: 10.0)

  • +
+
+
+
+
+template_fields: Sequence[str] = ('config_file', 'name', 'namespace', 'cluster_context')[source]
+
+ +
+
+hook()[source]
+
+
+
+ +
+
+client()[source]
+
+
+
+ +
+
+execute(context)[source]
+

Derive when creating an operator.

+

Context is the same dictionary used as when rendering jinja templates.

+

Refer to get_template_context for more context.

+
+
+
+ +
+ +
+
+class airflow.providers.cncf.kubernetes.operators.job.KubernetesPatchJobOperator(*, name, namespace, body, kubernetes_conn_id=KubernetesHook.default_conn_name, config_file=None, in_cluster=None, cluster_context=None, **kwargs)[source]
+

Bases: airflow.models.BaseOperator

+

Update a Kubernetes Job.

+
+

See also

+

For more information on how to use this operator, take a look at the guide: +KubernetesPatchJobOperator

+
+
+
Parameters
+
    +
  • name (str) – name of the Job

  • +
  • namespace (str) – the namespace to run within kubernetes

  • +
  • body (object) – Job json object with parameters for update +https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#job-v1-batch +e.g. {"spec": {"suspend": True}}

  • +
  • kubernetes_conn_id (str | None) – The kubernetes connection id +for the Kubernetes cluster.

  • +
  • config_file (str | None) – The path to the Kubernetes config file. (templated) +If not specified, default value is ~/.kube/config

  • +
  • in_cluster (bool | None) – run kubernetes client with in_cluster configuration.

  • +
  • cluster_context (str | None) – context that points to kubernetes cluster. +Ignored when in_cluster is True. If None, current-context is used. (templated)

  • +
+
+
+
+
+template_fields: Sequence[str] = ('config_file', 'name', 'namespace', 'body', 'cluster_context')[source]
+
+ +
+
+hook()[source]
+
+
+
+ +
+
+execute(context)[source]
+

Derive when creating an operator.

+

Context is the same dictionary used as when rendering jinja templates.

+

Refer to get_template_context for more context.

+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/kubernetes_pod/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/kubernetes_pod/index.html new file mode 100644 index 00000000000..3dc20fd3f34 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/kubernetes_pod/index.html @@ -0,0 +1,893 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.operators.kubernetes_pod — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+ +
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/pod/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/pod/index.html new file mode 100644 index 00000000000..440ba7661d2 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/pod/index.html @@ -0,0 +1,1355 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.operators.pod — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.operators.pod

+

Executes task in a Kubernetes POD.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + +

PodEventType

Type of Events emitted by kubernetes pod.

KubernetesPodOperator

Execute a task in a Kubernetes Pod.

+
+
+

Attributes

+ ++++ + + + + + + + + +

alphanum_lower

KUBE_CONFIG_ENV_VAR

+
+
+airflow.providers.cncf.kubernetes.operators.pod.alphanum_lower[source]
+
+ +
+
+airflow.providers.cncf.kubernetes.operators.pod.KUBE_CONFIG_ENV_VAR = 'KUBECONFIG'[source]
+
+ +
+
+class airflow.providers.cncf.kubernetes.operators.pod.PodEventType[source]
+

Bases: enum.Enum

+

Type of Events emitted by kubernetes pod.

+
+
+WARNING = 'Warning'[source]
+
+ +
+
+NORMAL = 'Normal'[source]
+
+ +
+ +
+
+exception airflow.providers.cncf.kubernetes.operators.pod.PodReattachFailure[source]
+

Bases: airflow.exceptions.AirflowException

+

When we expect to be able to find a pod but cannot.

+
+ +
+
+class airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator(*, kubernetes_conn_id=KubernetesHook.default_conn_name, namespace=None, image=None, name=None, random_name_suffix=True, cmds=None, arguments=None, ports=None, volume_mounts=None, volumes=None, env_vars=None, env_from=None, secrets=None, in_cluster=None, cluster_context=None, labels=None, reattach_on_restart=True, startup_timeout_seconds=120, startup_check_interval_seconds=5, get_logs=True, container_logs=BASE_CONTAINER_NAME, image_pull_policy=None, annotations=None, container_resources=None, affinity=None, config_file=None, node_selector=None, image_pull_secrets=None, service_account_name=None, hostnetwork=False, host_aliases=None, tolerations=None, security_context=None, container_security_context=None, dnspolicy=None, dns_config=None, hostname=None, subdomain=None, schedulername=None, full_pod_spec=None, init_containers=None, log_events_on_failure=False, do_xcom_push=False, pod_template_file=None, pod_template_dict=None, priority_class_name=None, pod_runtime_info_envs=None, termination_grace_period=None, configmaps=None, skip_on_exit_code=None, base_container_name=None, deferrable=conf.getboolean('operators', 'default_deferrable', fallback=False), poll_interval=2, log_pod_spec_on_failure=True, on_finish_action='delete_pod', is_delete_operator_pod=None, termination_message_policy='File', active_deadline_seconds=None, callbacks=None, progress_callback=None, logging_interval=None, **kwargs)[source]
+

Bases: airflow.models.BaseOperator

+

Execute a task in a Kubernetes Pod.

+
+

See also

+

For more information on how to use this operator, take a look at the guide: +KubernetesPodOperator

+
+
+

Note

+

If you use Google Kubernetes Engine +and Airflow is not running in the same cluster, consider using +GKEStartPodOperator, which +simplifies the authorization process.

+
+
+
Parameters
+
    +
  • kubernetes_conn_id (str | None) – The kubernetes connection id +for the Kubernetes cluster.

  • +
  • namespace (str | None) – the namespace to run within kubernetes.

  • +
  • image (str | None) – Docker image you wish to launch. Defaults to hub.docker.com, +but fully qualified URLS will point to custom repositories. (templated)

  • +
  • name (str | None) – name of the pod in which the task will run, will be used (plus a random +suffix if random_name_suffix is True) to generate a pod id (DNS-1123 subdomain, +containing only [a-z0-9.-]).

  • +
  • random_name_suffix (bool) – if True, will generate a random suffix.

  • +
  • cmds (list[str] | None) – entrypoint of the container. (templated) +The docker images’s entrypoint is used if this is not provided.

  • +
  • arguments (list[str] | None) – arguments of the entrypoint. (templated) +The docker image’s CMD is used if this is not provided.

  • +
  • ports (list[kubernetes.client.models.V1ContainerPort] | None) – ports for the launched pod.

  • +
  • volume_mounts (list[kubernetes.client.models.V1VolumeMount] | None) – volumeMounts for the launched pod.

  • +
  • volumes (list[kubernetes.client.models.V1Volume] | None) – volumes for the launched pod. Includes ConfigMaps and PersistentVolumes.

  • +
  • env_vars (list[kubernetes.client.models.V1EnvVar] | dict[str, str] | None) – Environment variables initialized in the container. (templated)

  • +
  • env_from (list[kubernetes.client.models.V1EnvFromSource] | None) – (Optional) List of sources to populate environment variables in the container.

  • +
  • secrets (list[airflow.providers.cncf.kubernetes.secret.Secret] | None) – Kubernetes secrets to inject in the container. +They can be exposed as environment vars or files in a volume.

  • +
  • in_cluster (bool | None) – run kubernetes client with in_cluster configuration.

  • +
  • cluster_context (str | None) – context that points to kubernetes cluster. +Ignored when in_cluster is True. If None, current-context is used. (templated)

  • +
  • reattach_on_restart (bool) – if the worker dies while the pod is running, reattach and monitor +during the next try. If False, always create a new pod for each try.

  • +
  • labels (dict | None) – labels to apply to the Pod. (templated)

  • +
  • startup_timeout_seconds (int) – timeout in seconds to startup the pod.

  • +
  • startup_check_interval_seconds (int) – interval in seconds to check if the pod has already started

  • +
  • get_logs (bool) – get the stdout of the base container as logs of the tasks.

  • +
  • container_logs (Iterable[str] | str | typing_extensions.Literal[True]) – list of containers whose logs will be published to stdout +Takes a sequence of containers, a single container name or True. If True, +all the containers logs are published. Works in conjunction with get_logs param. +The default value is the base container.

  • +
  • image_pull_policy (str | None) – Specify a policy to cache or always pull an image.

  • +
  • annotations (dict | None) – non-identifying metadata you can attach to the Pod. +Can be a large range of data, and can include characters +that are not permitted by labels. (templated)

  • +
  • container_resources (kubernetes.client.models.V1ResourceRequirements | None) – resources for the launched pod. (templated)

  • +
  • affinity (kubernetes.client.models.V1Affinity | None) – affinity scheduling rules for the launched pod.

  • +
  • config_file (str | None) – The path to the Kubernetes config file. (templated) +If not specified, default value is ~/.kube/config

  • +
  • node_selector (dict | None) – A dict containing a group of scheduling rules.

  • +
  • image_pull_secrets (list[kubernetes.client.models.V1LocalObjectReference] | None) – Any image pull secrets to be given to the pod. +If more than one secret is required, provide a +comma separated list: secret_a,secret_b

  • +
  • service_account_name (str | None) – Name of the service account

  • +
  • hostnetwork (bool) – If True enable host networking on the pod.

  • +
  • host_aliases (list[kubernetes.client.models.V1HostAlias] | None) – A list of host aliases to apply to the containers in the pod.

  • +
  • tolerations (list[kubernetes.client.models.V1Toleration] | None) – A list of kubernetes tolerations.

  • +
  • security_context (kubernetes.client.models.V1PodSecurityContext | dict | None) – security options the pod should run with (PodSecurityContext).

  • +
  • container_security_context (kubernetes.client.models.V1SecurityContext | dict | None) – security options the container should run with.

  • +
  • dnspolicy (str | None) – dnspolicy for the pod.

  • +
  • dns_config (kubernetes.client.models.V1PodDNSConfig | None) – dns configuration (ip addresses, searches, options) for the pod.

  • +
  • hostname (str | None) – hostname for the pod.

  • +
  • subdomain (str | None) – subdomain for the pod.

  • +
  • schedulername (str | None) – Specify a schedulername for the pod

  • +
  • full_pod_spec (kubernetes.client.models.V1Pod | None) – The complete podSpec

  • +
  • init_containers (list[kubernetes.client.models.V1Container] | None) – init container for the launched Pod

  • +
  • log_events_on_failure (bool) – Log the pod’s events if a failure occurs

  • +
  • do_xcom_push (bool) – If True, the content of the file +/airflow/xcom/return.json in the container will also be pushed to an +XCom when the container completes.

  • +
  • pod_template_file (str | None) – path to pod template file (templated)

  • +
  • pod_template_dict (dict | None) – pod template dictionary (templated)

  • +
  • priority_class_name (str | None) – priority class name for the launched Pod

  • +
  • pod_runtime_info_envs (list[kubernetes.client.models.V1EnvVar] | None) – (Optional) A list of environment variables, +to be set in the container.

  • +
  • termination_grace_period (int | None) – Termination grace period if task killed in UI, +defaults to kubernetes default

  • +
  • configmaps (list[str] | None) – (Optional) A list of names of config maps from which it collects ConfigMaps +to populate the environment variables with. The contents of the target +ConfigMap’s Data field will represent the key-value pairs as environment variables. +Extends env_from.

  • +
  • skip_on_exit_code (int | collections.abc.Container[int] | None) – If task exits with this exit code, leave the task +in skipped state (default: None). If set to None, any non-zero +exit code will be treated as a failure.

  • +
  • base_container_name (str | None) – The name of the base container in the pod. This container’s logs +will appear as part of this task’s logs if get_logs is True. Defaults to None. If None, +will consult the class variable BASE_CONTAINER_NAME (which defaults to “base”) for the base +container name to use.

  • +
  • deferrable (bool) – Run operator in the deferrable mode.

  • +
  • poll_interval (float) – Polling period in seconds to check for the status. Used only in deferrable mode.

  • +
  • log_pod_spec_on_failure (bool) – Log the pod’s specification if a failure occurs

  • +
  • on_finish_action (str) – What to do when the pod reaches its final state, or the execution is interrupted. +If “delete_pod”, the pod will be deleted regardless its state; if “delete_succeeded_pod”, +only succeeded pod will be deleted. You can set to “keep_pod” to keep the pod.

  • +
  • is_delete_operator_pod (None | bool) – What to do when the pod reaches its final +state, or the execution is interrupted. If True (default), delete the +pod; if False, leave the pod. +Deprecated - use on_finish_action instead.

  • +
  • termination_message_policy (str) – The termination message policy of the base container. +Default value is “File”

  • +
  • active_deadline_seconds (int | None) – The active_deadline_seconds which translates to active_deadline_seconds +in V1PodSpec.

  • +
  • callbacks (type[airflow.providers.cncf.kubernetes.callbacks.KubernetesPodOperatorCallback] | None) – KubernetesPodOperatorCallback instance contains the callbacks methods on different step +of KubernetesPodOperator.

  • +
  • progress_callback (Callable[[str], None] | None) – Callback function for receiving k8s container logs. +progress_callback is deprecated, please use :param callbacks instead.

  • +
  • logging_interval (int | None) – max time in seconds that task should be in deferred state before +resuming to fetch the latest logs. If None, then the task will remain in deferred state until pod +is done, and no logs will be visible until that time.

  • +
+
+
+
+
+BASE_CONTAINER_NAME = 'base'[source]
+
+ +
+
+ISTIO_CONTAINER_NAME = 'istio-proxy'[source]
+
+ +
+
+KILL_ISTIO_PROXY_SUCCESS_MSG = 'HTTP/1.1 200'[source]
+
+ +
+
+POD_CHECKED_KEY = 'already_checked'[source]
+
+ +
+
+POST_TERMINATION_TIMEOUT = 120[source]
+
+ +
+
+template_fields: Sequence[str] = ('image', 'cmds', 'annotations', 'arguments', 'env_vars', 'labels', 'config_file',...[source]
+
+ +
+
+template_fields_renderers[source]
+
+ +
+
+pod_manager()[source]
+
+
+
+ +
+
+hook()[source]
+
+
+
+ +
+
+client()[source]
+
+
+
+ +
+
+find_pod(namespace, context, *, exclude_checked=True)[source]
+

Return an already-running pod for this task instance if one exists.

+
+
+
+ +
+
+get_or_create_pod(pod_request_obj, context)[source]
+
+
+
+ +
+
+await_pod_start(pod)[source]
+
+
+
+ +
+
+extract_xcom(pod)[source]
+

Retrieve xcom value and kill xcom sidecar container.

+
+
+
+ +
+
+execute(context)[source]
+

Based on the deferrable parameter runs the pod asynchronously or synchronously.

+
+
+
+ +
+
+execute_sync(context)[source]
+
+
+
+ +
+
+execute_async(context)[source]
+
+
+
+ +
+
+invoke_defer_method(last_log_time=None)[source]
+

Redefine triggers which are being used in child classes.

+
+
+
+ +
+
+trigger_reentry(context, event)[source]
+

Point of re-entry from trigger.

+

If logging_interval is None, then at this point, the pod should be done, and we’ll just fetch +the logs and exit.

+

If logging_interval is not None, it could be that the pod is still running, and we’ll just +grab the latest logs and defer back to the trigger again.

+
+
+
+ +
+
+execute_complete(context, event, **kwargs)[source]
+
+
+
+ +
+
+write_logs(pod, follow=False, since_time=None)[source]
+
+
+
+ +
+
+post_complete_action(*, pod, remote_pod, **kwargs)[source]
+

Actions that must be done after operator finishes logic of the deferrable_execution.

+
+ +
+
+cleanup(pod, remote_pod)[source]
+
+
+
+ +
+
+is_istio_enabled(pod)[source]
+

Check if istio is enabled for the namespace of the pod by inspecting the namespace labels.

+
+
+
+ +
+
+kill_istio_sidecar(pod)[source]
+
+
+
+ +
+
+process_pod_deletion(pod, *, reraise=True)[source]
+
+
+
+ +
+
+patch_already_checked(pod, *, reraise=True)[source]
+

Add an “already checked” annotation to ensure we don’t reattach on retries.

+
+
+
+ +
+
+on_kill()[source]
+

Override this method to clean up subprocesses when a task instance gets killed.

+

Any use of the threading, subprocess or multiprocessing module within an +operator needs to be cleaned up, or it will leave ghost processes behind.

+
+
+
+ +
+
+build_pod_request_obj(context=None)[source]
+

Return V1Pod object based on pod template file, full pod spec, and other operator parameters.

+

The V1Pod attributes are derived (in order of precedence) from operator params, full pod spec, pod +template file.

+
+
+
+ +
+
+dry_run()[source]
+

Print out the pod definition that would be created by this operator.

+

Does not include labels specific to the task instance (since there isn’t +one in a dry_run) and excludes all empty elements.

+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/resource/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/resource/index.html new file mode 100644 index 00000000000..6e020865675 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/resource/index.html @@ -0,0 +1,983 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.operators.resource — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.operators.resource

+

Manage a Kubernetes Resource.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + +

KubernetesCreateResourceOperator

Create a resource in a kubernetes.

KubernetesDeleteResourceOperator

Delete a resource in a kubernetes.

+
+
+class airflow.providers.cncf.kubernetes.operators.resource.KubernetesCreateResourceOperator(*, yaml_conf=None, yaml_conf_file=None, namespace=None, kubernetes_conn_id=KubernetesHook.default_conn_name, custom_resource_definition=False, namespaced=True, config_file=None, **kwargs)[source]
+

Bases: KubernetesResourceBaseOperator

+

Create a resource in a kubernetes.

+
+
+
+
+create_custom_from_yaml_object(body)[source]
+
+
+
+ +
+
+execute(context)[source]
+

Derive when creating an operator.

+

Context is the same dictionary used as when rendering jinja templates.

+

Refer to get_template_context for more context.

+
+
+
+ +
+ +
+
+class airflow.providers.cncf.kubernetes.operators.resource.KubernetesDeleteResourceOperator(*, yaml_conf=None, yaml_conf_file=None, namespace=None, kubernetes_conn_id=KubernetesHook.default_conn_name, custom_resource_definition=False, namespaced=True, config_file=None, **kwargs)[source]
+

Bases: KubernetesResourceBaseOperator

+

Delete a resource in a kubernetes.

+
+
+
+
+delete_custom_from_yaml_object(body)[source]
+
+
+
+ +
+
+execute(context)[source]
+

Derive when creating an operator.

+

Context is the same dictionary used as when rendering jinja templates.

+

Refer to get_template_context for more context.

+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/spark_kubernetes/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/spark_kubernetes/index.html new file mode 100644 index 00000000000..10e1c3a89db --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/operators/spark_kubernetes/index.html @@ -0,0 +1,1116 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.operators.spark_kubernetes — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.operators.spark_kubernetes

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

SparkKubernetesOperator

Creates sparkApplication object in kubernetes cluster.

+
+
+class airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator(*, image=None, code_path=None, namespace='default', name='default', application_file=None, template_spec=None, get_logs=True, do_xcom_push=False, success_run_history_limit=1, startup_timeout_seconds=600, log_events_on_failure=False, reattach_on_restart=True, delete_on_termination=True, kubernetes_conn_id='kubernetes_default', **kwargs)[source]
+

Bases: airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator

+

Creates sparkApplication object in kubernetes cluster.

+
+

See also

+

For more detail about Spark Application Object have a look at the reference: +https://github.com/GoogleCloudPlatform/spark-on-k8s-operator/blob/v1beta2-1.3.3-3.1.1/docs/api-docs.md#sparkapplication

+
+
+
Parameters
+
    +
  • application_file (str | None) – filepath to kubernetes custom_resource_definition of sparkApplication

  • +
  • kubernetes_conn_id (str) – the connection to Kubernetes cluster

  • +
  • image (str | None) – Docker image you wish to launch. Defaults to hub.docker.com,

  • +
  • code_path (str | None) – path to the spark code in image,

  • +
  • namespace (str) – kubernetes namespace to put sparkApplication

  • +
  • cluster_context – context of the cluster

  • +
  • application_file – yaml file if passed

  • +
  • get_logs (bool) – get the stdout of the container as logs of the tasks.

  • +
  • do_xcom_push (bool) – If True, the content of the file +/airflow/xcom/return.json in the container will also be pushed to an +XCom when the container completes.

  • +
  • success_run_history_limit (int) – Number of past successful runs of the application to keep.

  • +
  • delete_on_termination (bool) – What to do when the pod reaches its final +state, or the execution is interrupted. If True (default), delete the +pod; if False, leave the pod.

  • +
  • startup_timeout_seconds – timeout in seconds to startup the pod.

  • +
  • log_events_on_failure (bool) – Log the pod’s events if a failure occurs

  • +
  • reattach_on_restart (bool) – if the scheduler dies while the pod is running, reattach and monitor

  • +
+
+
+
+
+property template_body[source]
+

Templated body for CustomObjectLauncher.

+
+ +
+
+template_fields = ['application_file', 'namespace', 'template_spec'][source]
+
+ +
+
+template_fields_renderers[source]
+
+ +
+
+template_ext = ('yaml', 'yml', 'json')[source]
+
+ +
+
+ui_color = '#f4a460'[source]
+
+ +
+
+BASE_CONTAINER_NAME = 'spark-kubernetes-driver'[source]
+
+ +
+
+manage_template_specs()[source]
+
+ +
+
+create_job_name()[source]
+
+ +
+
+static create_labels_for_pod(context=None, include_try_number=True)[source]
+

Generate labels for the pod to track the pod in case of Operator crash.

+
+
Parameters
+
    +
  • include_try_number (bool) – add try number to labels

  • +
  • context (dict | None) – task context provided by airflow DAG

  • +
+
+
Returns
+

dict.

+
+
Return type
+

dict

+
+
+
+ +
+
+pod_manager()[source]
+
+
+
+ +
+
+find_spark_job(context)[source]
+
+ +
+
+get_or_create_spark_crd(launcher, context)[source]
+
+
+
+ +
+
+process_pod_deletion(pod, *, reraise=True)[source]
+
+ +
+
+hook()[source]
+
+
+
+ +
+
+client()[source]
+
+
+
+ +
+
+custom_obj_api()[source]
+
+
+
+ +
+
+execute(context)[source]
+

Based on the deferrable parameter runs the pod asynchronously or synchronously.

+
+
+
+ +
+
+on_kill()[source]
+

Override this method to clean up subprocesses when a task instance gets killed.

+

Any use of the threading, subprocess or multiprocessing module within an +operator needs to be cleaned up, or it will leave ghost processes behind.

+
+
+
+ +
+
+patch_already_checked(pod, *, reraise=True)[source]
+

Add an “already checked” annotation to ensure we don’t reattach on retries.

+
+
+
+ +
+
+dry_run()[source]
+

Print out the spark job that would be created by this operator.

+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/pod_generator/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/pod_generator/index.html new file mode 100644 index 00000000000..58d263c735c --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/pod_generator/index.html @@ -0,0 +1,1332 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.pod_generator — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.pod_generator

+

Pod generator.

+

This module provides an interface between the previous Pod +API and outputs a kubernetes.client.models.V1Pod. +The advantage being that the full Kubernetes API +is supported and no serialization need be written.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

PodGenerator

Contains Kubernetes Airflow Worker configuration logic.

+
+
+

Functions

+ ++++ + + + + + + + + + + + + + + + + + +

make_safe_label_value(string)

Normalize a provided label to be of valid length and characters.

datetime_to_label_safe_datestring(datetime_obj)

Transform a datetime string to use as a label.

label_safe_datestring_to_datetime(string)

Transform a label back to a datetime object.

merge_objects(base_obj, client_obj)

Merge objects.

extend_object_field(base_obj, client_obj, field_name)

Add field values to existing objects.

+
+
+

Attributes

+ ++++ + + + + + + + + +

log

MAX_LABEL_LEN

+
+
+airflow.providers.cncf.kubernetes.pod_generator.log[source]
+
+ +
+
+airflow.providers.cncf.kubernetes.pod_generator.MAX_LABEL_LEN = 63[source]
+
+ +
+
+exception airflow.providers.cncf.kubernetes.pod_generator.PodMutationHookException[source]
+

Bases: airflow.exceptions.AirflowException

+

Raised when exception happens during Pod Mutation Hook execution.

+
+ +
+
+exception airflow.providers.cncf.kubernetes.pod_generator.PodReconciliationError[source]
+

Bases: airflow.exceptions.AirflowException

+

Raised when an error is encountered while trying to merge pod configs.

+
+ +
+
+airflow.providers.cncf.kubernetes.pod_generator.make_safe_label_value(string)[source]
+

Normalize a provided label to be of valid length and characters.

+

Valid label values must be 63 characters or less and must be empty or begin and +end with an alphanumeric character ([a-z0-9A-Z]) with dashes (-), underscores (_), +dots (.), and alphanumerics between.

+

If the label value is greater than 63 chars once made safe, or differs in any +way from the original value sent to this function, then we need to truncate to +53 chars, and append it with a unique hash.

+
+
+
+ +
+
+airflow.providers.cncf.kubernetes.pod_generator.datetime_to_label_safe_datestring(datetime_obj)[source]
+

Transform a datetime string to use as a label.

+

Kubernetes doesn’t like “:” in labels, since ISO datetime format uses “:” but +not “_” let’s +replace “:” with “_”

+
+
Parameters
+

datetime_obj (datetime.datetime) – datetime.datetime object

+
+
Returns
+

ISO-like string representing the datetime

+
+
Return type
+

str

+
+
+
+ +
+
+airflow.providers.cncf.kubernetes.pod_generator.label_safe_datestring_to_datetime(string)[source]
+

Transform a label back to a datetime object.

+

Kubernetes doesn’t permit “:” in labels. ISO datetime format uses “:” but not +“_”, let’s +replace “:” with “_”

+
+
Parameters
+

string (str) – str

+
+
Returns
+

datetime.datetime object

+
+
Return type
+

datetime.datetime

+
+
+
+ +
+
+class airflow.providers.cncf.kubernetes.pod_generator.PodGenerator(pod=None, pod_template_file=None, extract_xcom=True)[source]
+

Contains Kubernetes Airflow Worker configuration logic.

+

Represents a kubernetes pod and manages execution of a single pod. +Any configuration that is container specific gets applied to +the first container in the list of containers.

+
+
Parameters
+
    +
  • pod (kubernetes.client.models.V1Pod | None) – The fully specified pod. Mutually exclusive with pod_template_file

  • +
  • pod_template_file (str | None) – Path to YAML file. Mutually exclusive with pod

  • +
  • extract_xcom (bool) – Whether to bring up a container for xcom

  • +
+
+
+
+
+gen_pod()[source]
+

Generate pod.

+
+
+
+ +
+
+static add_xcom_sidecar(pod)[source]
+

Add sidecar.

+
+
+
+ +
+
+static from_obj(obj)[source]
+

Convert to pod from obj.

+
+
+
+ +
+
+static from_legacy_obj(obj)[source]
+

Convert to pod from obj.

+
+
+
+ +
+
+static reconcile_pods(base_pod, client_pod)[source]
+

Merge Kubernetes Pod objects.

+
+
Parameters
+
    +
  • base_pod (kubernetes.client.models.V1Pod) – has the base attributes which are overwritten if they exist +in the client pod and remain if they do not exist in the client_pod

  • +
  • client_pod (kubernetes.client.models.V1Pod | None) – the pod that the client wants to create.

  • +
+
+
Returns
+

the merged pods

+
+
Return type
+

kubernetes.client.models.V1Pod

+
+
+

This can’t be done recursively as certain fields are overwritten and some are concatenated.

+
+ +
+
+static reconcile_metadata(base_meta, client_meta)[source]
+

Merge Kubernetes Metadata objects.

+
+
Parameters
+
    +
  • base_meta – has the base attributes which are overwritten if they exist +in the client_meta and remain if they do not exist in the client_meta

  • +
  • client_meta – the spec that the client wants to create.

  • +
+
+
Returns
+

the merged specs

+
+
+
+ +
+
+static reconcile_specs(base_spec, client_spec)[source]
+

Merge Kubernetes PodSpec objects.

+
+
Parameters
+
    +
  • base_spec (kubernetes.client.models.V1PodSpec | None) – has the base attributes which are overwritten if they exist +in the client_spec and remain if they do not exist in the client_spec

  • +
  • client_spec (kubernetes.client.models.V1PodSpec | None) – the spec that the client wants to create.

  • +
+
+
Returns
+

the merged specs

+
+
Return type
+

kubernetes.client.models.V1PodSpec | None

+
+
+
+ +
+
+static reconcile_containers(base_containers, client_containers)[source]
+

Merge Kubernetes Container objects.

+
+
Parameters
+
    +
  • base_containers (list[kubernetes.client.models.V1Container]) – has the base attributes which are overwritten if they exist +in the client_containers and remain if they do not exist in the client_containers

  • +
  • client_containers (list[kubernetes.client.models.V1Container]) – the containers that the client wants to create.

  • +
+
+
Returns
+

the merged containers

+
+
Return type
+

list[kubernetes.client.models.V1Container]

+
+
+

The runs recursively over the list of containers.

+
+ +
+
+classmethod construct_pod(dag_id, task_id, pod_id, try_number, kube_image, date, args, pod_override_object, base_worker_pod, namespace, scheduler_job_id, run_id=None, map_index=-1, *, with_mutation_hook=False)[source]
+

Create a Pod.

+
+
Construct a pod by gathering and consolidating the configuration from 3 places:
    +
  • airflow.cfg

  • +
  • executor_config

  • +
  • dynamic arguments

  • +
+
+
+
+
+
+ +
+
+static serialize_pod(pod)[source]
+

Convert a k8s.V1Pod into a json serializable dictionary.

+
+
Parameters
+

pod (kubernetes.client.models.V1Pod) – k8s.V1Pod object

+
+
Returns
+

Serialized version of the pod returned as dict

+
+
Return type
+

dict

+
+
+
+ +
+
+static deserialize_model_file(path)[source]
+

Generate a Pod from a file.

+
+
Parameters
+

path (str) – Path to the file

+
+
Returns
+

a kubernetes.client.models.V1Pod

+
+
Return type
+

kubernetes.client.models.V1Pod

+
+
+
+ +
+
+static deserialize_model_dict(pod_dict)[source]
+

Deserializes a Python dictionary to k8s.V1Pod.

+

Unfortunately we need access to the private method +_ApiClient__deserialize_model from the kubernetes client. +This issue is tracked here; https://github.com/kubernetes-client/python/issues/977.

+
+
Parameters
+

pod_dict (dict | None) – Serialized dict of k8s.V1Pod object

+
+
Returns
+

De-serialized k8s.V1Pod

+
+
Return type
+

kubernetes.client.models.V1Pod

+
+
+
+ +
+
+static make_unique_pod_id(pod_id)[source]
+

Generate a unique Pod name.

+

Kubernetes pod names must consist of one or more lowercase +rfc1035/rfc1123 labels separated by ‘.’ with a maximum length of 253 +characters.

+

Name must pass the following regex for validation +^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$

+

For more details, see: +https://github.com/kubernetes/kubernetes/blob/release-1.1/docs/design/identifiers.md

+
+
Parameters
+

pod_id (str) – requested pod name

+
+
Returns
+

str valid Pod name of appropriate length

+
+
Return type
+

str | None

+
+
+
+ +
+ +
+
+airflow.providers.cncf.kubernetes.pod_generator.merge_objects(base_obj, client_obj)[source]
+

Merge objects.

+
+
Parameters
+
    +
  • base_obj – has the base attributes which are overwritten if they exist +in the client_obj and remain if they do not exist in the client_obj

  • +
  • client_obj – the object that the client wants to create.

  • +
+
+
Returns
+

the merged objects

+
+
+
+ +
+
+airflow.providers.cncf.kubernetes.pod_generator.extend_object_field(base_obj, client_obj, field_name)[source]
+

Add field values to existing objects.

+
+
Parameters
+
    +
  • base_obj – an object which has a property field_name that is a list

  • +
  • client_obj – an object which has a property field_name that is a list. +A copy of this object is returned with field_name modified

  • +
  • field_name – the name of the list field

  • +
+
+
Returns
+

the client_obj with the property field_name being the two properties appended

+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/pod_generator_deprecated/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/pod_generator_deprecated/index.html new file mode 100644 index 00000000000..ff8904cc4b3 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/pod_generator_deprecated/index.html @@ -0,0 +1,1121 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.pod_generator_deprecated — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.pod_generator_deprecated

+

Backwards compatibility for Pod generation.

+

This module provides an interface between the previous Pod +API and outputs a kubernetes.client.models.V1Pod. +The advantage being that the full Kubernetes API +is supported and no serialization need be written.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + +

PodDefaults

Static defaults for Pods.

PodGenerator

Contains Kubernetes Airflow Worker configuration logic.

+
+
+

Functions

+ ++++ + + + + + +

make_safe_label_value(string)

Normalize a provided label to be of valid length and characters.

+
+
+

Attributes

+ ++++ + + + + + + + + +

MAX_POD_ID_LEN

MAX_LABEL_LEN

+
+
+airflow.providers.cncf.kubernetes.pod_generator_deprecated.MAX_POD_ID_LEN = 253[source]
+
+ +
+
+airflow.providers.cncf.kubernetes.pod_generator_deprecated.MAX_LABEL_LEN = 63[source]
+
+ +
+
+class airflow.providers.cncf.kubernetes.pod_generator_deprecated.PodDefaults[source]
+

Static defaults for Pods.

+
+
+XCOM_MOUNT_PATH = '/airflow/xcom'[source]
+
+ +
+
+SIDECAR_CONTAINER_NAME = 'airflow-xcom-sidecar'[source]
+
+ +
+
+XCOM_CMD = 'trap "exit 0" INT; while true; do sleep 30; done;'[source]
+
+ +
+
+VOLUME_MOUNT[source]
+
+ +
+
+VOLUME[source]
+
+ +
+
+SIDECAR_CONTAINER[source]
+
+ +
+ +
+
+airflow.providers.cncf.kubernetes.pod_generator_deprecated.make_safe_label_value(string)[source]
+

Normalize a provided label to be of valid length and characters.

+

Valid label values must be 63 characters or less and must be empty or begin and +end with an alphanumeric character ([a-z0-9A-Z]) with dashes (-), underscores (_), +dots (.), and alphanumerics between.

+

If the label value is greater than 63 chars once made safe, or differs in any +way from the original value sent to this function, then we need to truncate to +53 chars, and append it with a unique hash.

+
+ +
+
+class airflow.providers.cncf.kubernetes.pod_generator_deprecated.PodGenerator(image=None, name=None, namespace=None, volume_mounts=None, envs=None, cmds=None, args=None, labels=None, node_selectors=None, ports=None, volumes=None, image_pull_policy=None, restart_policy=None, image_pull_secrets=None, init_containers=None, service_account_name=None, resources=None, annotations=None, affinity=None, hostnetwork=False, tolerations=None, security_context=None, configmaps=None, dnspolicy=None, schedulername=None, extract_xcom=False, priority_class_name=None)[source]
+

Contains Kubernetes Airflow Worker configuration logic.

+

Represents a kubernetes pod and manages execution of a single pod. +Any configuration that is container specific gets applied to +the first container in the list of containers.

+
+
Parameters
+
    +
  • image (str | None) – The docker image

  • +
  • name (str | None) – name in the metadata section (not the container name)

  • +
  • namespace (str | None) – pod namespace

  • +
  • volume_mounts (list[kubernetes.client.models.V1VolumeMount | dict] | None) – list of kubernetes volumes mounts

  • +
  • envs (dict[str, str] | None) – A dict containing the environment variables

  • +
  • cmds (list[str] | None) – The command to be run on the first container

  • +
  • args (list[str] | None) – The arguments to be run on the pod

  • +
  • labels (dict[str, str] | None) – labels for the pod metadata

  • +
  • node_selectors (dict[str, str] | None) – node selectors for the pod

  • +
  • ports (list[kubernetes.client.models.V1ContainerPort | dict] | None) – list of ports. Applies to the first container.

  • +
  • volumes (list[kubernetes.client.models.V1Volume | dict] | None) – Volumes to be attached to the first container

  • +
  • image_pull_policy (str | None) – Specify a policy to cache or always pull an image

  • +
  • restart_policy (str | None) – The restart policy of the pod

  • +
  • image_pull_secrets (str | None) – Any image pull secrets to be given to the pod. +If more than one secret is required, provide a comma separated list: +secret_a,secret_b

  • +
  • init_containers (list[kubernetes.client.models.V1Container] | None) – A list of init containers

  • +
  • service_account_name (str | None) – Identity for processes that run in a Pod

  • +
  • resources (kubernetes.client.models.V1ResourceRequirements | dict | None) – Resource requirements for the first containers

  • +
  • annotations (dict[str, str] | None) – annotations for the pod

  • +
  • affinity (dict | None) – A dict containing a group of affinity scheduling rules

  • +
  • hostnetwork (bool) – If True enable host networking on the pod

  • +
  • tolerations (list | None) – A list of kubernetes tolerations

  • +
  • security_context (kubernetes.client.models.V1PodSecurityContext | dict | None) – A dict containing the security context for the pod

  • +
  • configmaps (list[str] | None) – Any configmap refs to read configmaps for environments from. +If more than one configmap is required, provide a comma separated list +configmap_a,configmap_b

  • +
  • dnspolicy (str | None) – Specify a dnspolicy for the pod

  • +
  • schedulername (str | None) – Specify a schedulername for the pod

  • +
  • pod – The fully specified pod. Mutually exclusive with path_or_string

  • +
  • extract_xcom (bool) – Whether to bring up a container for xcom

  • +
  • priority_class_name (str | None) – priority class name for the launched Pod

  • +
+
+
+
+
+gen_pod()[source]
+

Generate pod.

+
+
+
+ +
+
+static add_sidecar(pod)[source]
+

Add sidecar.

+
+
+
+ +
+
+static from_obj(obj)[source]
+

Convert to pod from obj.

+
+
+
+ +
+
+static make_unique_pod_id(dag_id)[source]
+

Generate a unique Pod name.

+

Kubernetes pod names must be <= 253 chars and must pass the following regex for +validation +^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$

+
+
Parameters
+

dag_id – a dag_id with only alphanumeric characters

+
+
Returns
+

str valid Pod name of appropriate length

+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/pod_launcher_deprecated/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/pod_launcher_deprecated/index.html new file mode 100644 index 00000000000..4423550a401 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/pod_launcher_deprecated/index.html @@ -0,0 +1,1093 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.pod_launcher_deprecated — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.pod_launcher_deprecated

+

Launches pods.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + +

PodStatus

Status of the pods.

PodLauncher

Deprecated class for launching pods.

+
+
+class airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodStatus[source]
+

Status of the pods.

+
+
+PENDING = 'pending'[source]
+
+ +
+
+RUNNING = 'running'[source]
+
+ +
+
+FAILED = 'failed'[source]
+
+ +
+
+SUCCEEDED = 'succeeded'[source]
+
+ +
+ +
+
+class airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodLauncher(kube_client=None, in_cluster=True, cluster_context=None, extract_xcom=False)[source]
+

Bases: airflow.utils.log.logging_mixin.LoggingMixin

+

Deprecated class for launching pods.

+

Please use airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager instead.

+
+
+
+
+run_pod_async(pod, **kwargs)[source]
+

Run pod asynchronously.

+
+
+
+ +
+
+delete_pod(pod)[source]
+

Delete pod.

+
+
+
+ +
+
+start_pod(pod, startup_timeout=120)[source]
+

Launch the pod synchronously and wait for completion.

+
+
Parameters
+
    +
  • pod (kubernetes.client.models.v1_pod.V1Pod) –

  • +
  • startup_timeout (int) – Timeout for startup of the pod (if pod is pending for too long, fails task)

  • +
+
+
Returns
+

+
+
+
+ +
+
+monitor_pod(pod, get_logs)[source]
+

Monitor a pod and return the final state.

+
+
Parameters
+
    +
  • pod (kubernetes.client.models.v1_pod.V1Pod) – pod spec that will be monitored

  • +
  • get_logs (bool) – whether to read the logs locally

  • +
+
+
+
+ +
+
+parse_log_line(line)[source]
+

Parse K8s log line and returns the final state.

+
+
Parameters
+

line (str) – k8s log line

+
+
Returns
+

timestamp and log message

+
+
Return type
+

tuple[str | None, str]

+
+
+
+ +
+
+pod_not_started(pod)[source]
+

Test if pod has not started.

+
+
+
+ +
+
+pod_is_running(pod)[source]
+

Test if pod is running.

+
+
+
+ +
+
+base_container_is_running(pod)[source]
+

Test if base container is running.

+
+
+
+ +
+
+read_pod_logs(pod, tail_lines=None, timestamps=False, since_seconds=None)[source]
+

Read log from the pod.

+
+
+
+ +
+
+read_pod_events(pod)[source]
+

Read events from the pod.

+
+ +
+
+read_pod(pod)[source]
+

Read pod information.

+
+
+
+ +
+
+process_status(job_id, status)[source]
+

Process status information for the job.

+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/pod_template_file_examples/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/pod_template_file_examples/index.html new file mode 100644 index 00000000000..74b9b1cdfcb --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/pod_template_file_examples/index.html @@ -0,0 +1,890 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.pod_template_file_examples — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/python_kubernetes_script/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/python_kubernetes_script/index.html new file mode 100644 index 00000000000..211217ceaf4 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/python_kubernetes_script/index.html @@ -0,0 +1,952 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.python_kubernetes_script — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.python_kubernetes_script

+

Utilities for using the kubernetes decorator.

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + + + + +

remove_task_decorator(python_source, task_decorator_name)

Remove @task.kubernetes or similar as well as @setup and @teardown.

write_python_script(jinja_context, filename[, ...])

Render the python script to a file to execute in the virtual environment.

+
+
+airflow.providers.cncf.kubernetes.python_kubernetes_script.remove_task_decorator(python_source, task_decorator_name)[source]
+

Remove @task.kubernetes or similar as well as @setup and @teardown.

+
+
Parameters
+
    +
  • python_source (str) – python source code

  • +
  • task_decorator_name (str) – the task decorator name

  • +
+
+
+
+ +
+
+airflow.providers.cncf.kubernetes.python_kubernetes_script.write_python_script(jinja_context, filename, render_template_as_native_obj=False)[source]
+

Render the python script to a file to execute in the virtual environment.

+
+
Parameters
+
    +
  • jinja_context (dict) – The jinja context variables to unpack and replace with its placeholders in the +template file.

  • +
  • filename (str) – The name of the file to dump the rendered script to.

  • +
  • render_template_as_native_obj (bool) – If True, rendered Jinja template would be converted +to a native Python object

  • +
+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/resource_convert/configmap/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/resource_convert/configmap/index.html new file mode 100644 index 00000000000..58307428c18 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/resource_convert/configmap/index.html @@ -0,0 +1,956 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.resource_convert.configmap — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.resource_convert.configmap

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + + + + +

convert_configmap(configmap_name)

Convert a str into an k8s object.

convert_configmap_to_volume(configmap_info)

Convert a dictionary of config_map_name and mount_path into k8s volume mount object and k8s volume.

+
+
+airflow.providers.cncf.kubernetes.resource_convert.configmap.convert_configmap(configmap_name)[source]
+

Convert a str into an k8s object.

+
+
Parameters
+

configmap_name – config map name

+
+
Returns
+

+
+
Return type
+

kubernetes.client.models.V1EnvFromSource

+
+
+
+ +
+
+airflow.providers.cncf.kubernetes.resource_convert.configmap.convert_configmap_to_volume(configmap_info)[source]
+

Convert a dictionary of config_map_name and mount_path into k8s volume mount object and k8s volume.

+
+
Parameters
+

configmap_info (dict[str, str]) – a dictionary of {config_map_name: mount_path}

+
+
Returns
+

+
+
Return type
+

tuple[list[kubernetes.client.models.V1Volume], list[kubernetes.client.models.V1VolumeMount]]

+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/resource_convert/env_variable/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/resource_convert/env_variable/index.html new file mode 100644 index 00000000000..973bd9e06e0 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/resource_convert/env_variable/index.html @@ -0,0 +1,935 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.resource_convert.env_variable — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.resource_convert.env_variable

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + +

convert_env_vars(env_vars)

Convert a dictionary of key:value into a list of env_vars.

+
+
+airflow.providers.cncf.kubernetes.resource_convert.env_variable.convert_env_vars(env_vars)[source]
+

Convert a dictionary of key:value into a list of env_vars.

+
+
Parameters
+

env_vars

+
+
Returns
+

+
+
Return type
+

list[kubernetes.client.models.V1EnvVar]

+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/resource_convert/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/resource_convert/index.html new file mode 100644 index 00000000000..4fc33bef666 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/resource_convert/index.html @@ -0,0 +1,903 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.resource_convert — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/resource_convert/secret/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/resource_convert/secret/index.html new file mode 100644 index 00000000000..de8811b3eb7 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/resource_convert/secret/index.html @@ -0,0 +1,956 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.resource_convert.secret — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.resource_convert.secret

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + + + + +

convert_secret(secret_name)

Convert a str into an k8s object.

convert_image_pull_secrets(image_pull_secrets)

Convert an image pull secret name into k8s local object reference.

+
+
+airflow.providers.cncf.kubernetes.resource_convert.secret.convert_secret(secret_name)[source]
+

Convert a str into an k8s object.

+
+
Parameters
+

secret_name (str) –

+
+
Returns
+

+
+
Return type
+

kubernetes.client.models.V1EnvFromSource

+
+
+
+ +
+
+airflow.providers.cncf.kubernetes.resource_convert.secret.convert_image_pull_secrets(image_pull_secrets)[source]
+

Convert an image pull secret name into k8s local object reference.

+
+
Parameters
+

image_pull_secrets (str) – comma separated string that contains secrets

+
+
Returns
+

+
+
Return type
+

list[kubernetes.client.models.V1LocalObjectReference]

+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/secret/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/secret/index.html new file mode 100644 index 00000000000..610296eb97e --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/secret/index.html @@ -0,0 +1,976 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.secret — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.secret

+

Classes for interacting with Kubernetes API.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

Secret

Defines Kubernetes Secret Volume.

+
+
+class airflow.providers.cncf.kubernetes.secret.Secret(deploy_type, deploy_target, secret, key=None, items=None)[source]
+

Bases: airflow.providers.cncf.kubernetes.k8s_model.K8SModel

+

Defines Kubernetes Secret Volume.

+
+
+to_env_secret()[source]
+

Store es environment secret.

+
+
+
+ +
+
+to_env_from_secret()[source]
+

Read from environment to secret.

+
+
+
+ +
+
+to_volume_secret()[source]
+

Convert to volume secret.

+
+
+
+ +
+
+attach_to_pod(pod)[source]
+

Attach to pod.

+
+
+
+ +
+
+__eq__(other)[source]
+

Return self==value.

+
+ +
+
+__repr__()[source]
+

Return repr(self).

+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/sensors/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/sensors/index.html new file mode 100644 index 00000000000..3d9abab8526 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/sensors/index.html @@ -0,0 +1,901 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.sensors — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/sensors/spark_kubernetes/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/sensors/spark_kubernetes/index.html new file mode 100644 index 00000000000..ab4eda025c5 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/sensors/spark_kubernetes/index.html @@ -0,0 +1,981 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.sensors.spark_kubernetes — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.sensors.spark_kubernetes

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

SparkKubernetesSensor

Checks sparkApplication object in kubernetes cluster.

+
+
+class airflow.providers.cncf.kubernetes.sensors.spark_kubernetes.SparkKubernetesSensor(*, application_name, attach_log=False, namespace=None, container_name='spark-kubernetes-driver', kubernetes_conn_id='kubernetes_default', api_group='sparkoperator.k8s.io', api_version='v1beta2', **kwargs)[source]
+

Bases: airflow.sensors.base.BaseSensorOperator

+

Checks sparkApplication object in kubernetes cluster.

+
+

See also

+

For more detail about Spark Application Object have a look at the reference: +https://github.com/GoogleCloudPlatform/spark-on-k8s-operator/blob/v1beta2-1.1.0-2.4.5/docs/api-docs.md#sparkapplication

+
+
+
Parameters
+
    +
  • application_name (str) – spark Application resource name

  • +
  • namespace (str | None) – the kubernetes namespace where the sparkApplication reside in

  • +
  • container_name (str) – the kubernetes container name where the sparkApplication reside in

  • +
  • kubernetes_conn_id (str) – The kubernetes connection +to Kubernetes cluster.

  • +
  • attach_log (bool) – determines whether logs for driver pod should be appended to the sensor log

  • +
  • api_group (str) – kubernetes api group of sparkApplication

  • +
  • api_version (str) – kubernetes api version of sparkApplication

  • +
+
+
+
+
+template_fields: Sequence[str] = ('application_name', 'namespace')[source]
+
+ +
+
+FAILURE_STATES = ('FAILED', 'UNKNOWN')[source]
+
+ +
+
+SUCCESS_STATES = ('COMPLETED',)[source]
+
+ +
+
+hook()[source]
+
+
+
+ +
+
+poke(context)[source]
+

Override when deriving this class.

+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/template_rendering/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/template_rendering/index.html new file mode 100644 index 00000000000..c8b10c1abcd --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/template_rendering/index.html @@ -0,0 +1,936 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.template_rendering — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.template_rendering

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + + + + +

render_k8s_pod_yaml(task_instance)

Render k8s pod yaml.

get_rendered_k8s_spec(task_instance[, session])

Fetch rendered template fields from DB.

+
+
+airflow.providers.cncf.kubernetes.template_rendering.render_k8s_pod_yaml(task_instance)[source]
+

Render k8s pod yaml.

+
+
+
+ +
+
+airflow.providers.cncf.kubernetes.template_rendering.get_rendered_k8s_spec(task_instance, session=NEW_SESSION)[source]
+

Fetch rendered template fields from DB.

+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/triggers/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/triggers/index.html new file mode 100644 index 00000000000..438ccb08a28 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/triggers/index.html @@ -0,0 +1,903 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.triggers — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/triggers/job/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/triggers/job/index.html new file mode 100644 index 00000000000..836ef0ff27f --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/triggers/job/index.html @@ -0,0 +1,967 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.triggers.job — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.triggers.job

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

KubernetesJobTrigger

KubernetesJobTrigger run on the trigger worker to check the state of Job.

+
+
+class airflow.providers.cncf.kubernetes.triggers.job.KubernetesJobTrigger(job_name, job_namespace, kubernetes_conn_id=None, poll_interval=10.0, cluster_context=None, config_file=None, in_cluster=None)[source]
+

Bases: airflow.triggers.base.BaseTrigger

+

KubernetesJobTrigger run on the trigger worker to check the state of Job.

+
+
Parameters
+
    +
  • job_name (str) – The name of the job.

  • +
  • job_namespace (str) – The namespace of the job.

  • +
  • kubernetes_conn_id (str | None) – The kubernetes connection id +for the Kubernetes cluster.

  • +
  • cluster_context (str | None) – Context that points to kubernetes cluster.

  • +
  • config_file (str | None) – Path to kubeconfig file.

  • +
  • poll_interval (float) – Polling period in seconds to check for the status.

  • +
  • in_cluster (bool | None) – run kubernetes client with in_cluster configuration.

  • +
+
+
+
+
+serialize()[source]
+

Serialize KubernetesCreateJobTrigger arguments and classpath.

+
+
+
+ +
+
+async run()[source]
+

Get current job status and yield a TriggerEvent.

+
+
+
+ +
+
+hook()[source]
+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/triggers/kubernetes_pod/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/triggers/kubernetes_pod/index.html new file mode 100644 index 00000000000..d52616511ad --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/triggers/kubernetes_pod/index.html @@ -0,0 +1,893 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.triggers.kubernetes_pod — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+ +
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/triggers/pod/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/triggers/pod/index.html new file mode 100644 index 00000000000..e2227e44fa6 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/triggers/pod/index.html @@ -0,0 +1,1041 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.triggers.pod — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.triggers.pod

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + +

ContainerState

Possible container states.

KubernetesPodTrigger

KubernetesPodTrigger run on the trigger worker to check the state of Pod.

+
+
+class airflow.providers.cncf.kubernetes.triggers.pod.ContainerState[source]
+

Bases: str, enum.Enum

+

Possible container states.

+

See https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase.

+
+
+WAITING = 'waiting'[source]
+
+ +
+
+RUNNING = 'running'[source]
+
+ +
+
+TERMINATED = 'terminated'[source]
+
+ +
+
+FAILED = 'failed'[source]
+
+ +
+
+UNDEFINED = 'undefined'[source]
+
+ +
+ +
+
+class airflow.providers.cncf.kubernetes.triggers.pod.KubernetesPodTrigger(pod_name, pod_namespace, trigger_start_time, base_container_name, kubernetes_conn_id=None, poll_interval=2, cluster_context=None, config_file=None, in_cluster=None, get_logs=True, startup_timeout=120, startup_check_interval=5, on_finish_action='delete_pod', should_delete_pod=None, last_log_time=None, logging_interval=None)[source]
+

Bases: airflow.triggers.base.BaseTrigger

+

KubernetesPodTrigger run on the trigger worker to check the state of Pod.

+
+
Parameters
+
    +
  • pod_name (str) – The name of the pod.

  • +
  • pod_namespace (str) – The namespace of the pod.

  • +
  • kubernetes_conn_id (str | None) – The kubernetes connection id +for the Kubernetes cluster.

  • +
  • cluster_context (str | None) – Context that points to kubernetes cluster.

  • +
  • config_file (str | None) – Path to kubeconfig file.

  • +
  • poll_interval (float) – Polling period in seconds to check for the status.

  • +
  • trigger_start_time (datetime.datetime) – time in Datetime format when the trigger was started

  • +
  • in_cluster (bool | None) – run kubernetes client with in_cluster configuration.

  • +
  • get_logs (bool) – get the stdout of the container as logs of the tasks.

  • +
  • startup_timeout (int) – timeout in seconds to start up the pod.

  • +
  • startup_check_interval (int) – interval in seconds to check if the pod has already started.

  • +
  • on_finish_action (str) – What to do when the pod reaches its final state, or the execution is interrupted. +If “delete_pod”, the pod will be deleted regardless its state; if “delete_succeeded_pod”, +only succeeded pod will be deleted. You can set to “keep_pod” to keep the pod.

  • +
  • should_delete_pod (bool | None) – What to do when the pod reaches its final +state, or the execution is interrupted. If True (default), delete the +pod; if False, leave the pod. +Deprecated - use on_finish_action instead.

  • +
  • logging_interval (int | None) – number of seconds to wait before kicking it back to +the operator to print latest logs. If None will wait until container done.

  • +
  • last_log_time (pendulum.DateTime | None) – where to resume logs from

  • +
+
+
+
+
+serialize()[source]
+

Serialize KubernetesCreatePodTrigger arguments and classpath.

+
+
+
+ +
+
+async run()[source]
+

Get current pod status and yield a TriggerEvent.

+
+
+
+ +
+
+hook()[source]
+
+
+
+ +
+
+define_container_state(pod)[source]
+
+
+
+ +
+
+static should_wait(pod_phase, container_state)[source]
+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/delete_from/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/delete_from/index.html new file mode 100644 index 00000000000..a9b20ee74a1 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/delete_from/index.html @@ -0,0 +1,974 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.utils.delete_from — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.utils.delete_from

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + + + + +

delete_from_dict(k8s_client, data, body, namespace[, ...])

delete_from_yaml(*, k8s_client[, yaml_objects, ...])

+
+
+

Attributes

+ ++++ + + + + + +

DEFAULT_DELETION_BODY

+
+
+airflow.providers.cncf.kubernetes.utils.delete_from.DEFAULT_DELETION_BODY[source]
+
+ +
+
+airflow.providers.cncf.kubernetes.utils.delete_from.delete_from_dict(k8s_client, data, body, namespace, verbose=False, **kwargs)[source]
+
+ +
+
+airflow.providers.cncf.kubernetes.utils.delete_from.delete_from_yaml(*, k8s_client, yaml_objects=None, verbose=False, namespace='default', body=None, **kwargs)[source]
+
+
+
+ +
+
+exception airflow.providers.cncf.kubernetes.utils.delete_from.FailToDeleteError(api_exceptions)[source]
+

Bases: Exception

+

For handling error if an error occurred when handling a yaml file during deletion of the resource.

+
+
+
+
+__str__()[source]
+

Return str(self).

+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/index.html new file mode 100644 index 00000000000..4132ec1f1ca --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/index.html @@ -0,0 +1,904 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.utils — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/k8s_resource_iterator/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/k8s_resource_iterator/index.html new file mode 100644 index 00000000000..dfe53feee6d --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/k8s_resource_iterator/index.html @@ -0,0 +1,925 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + +

k8s_resource_iterator(callback, resources)

+
+
+airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator.k8s_resource_iterator(callback, resources)[source]
+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/pod_manager/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/pod_manager/index.html new file mode 100644 index 00000000000..e336747944e --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/pod_manager/index.html @@ -0,0 +1,1423 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.utils.pod_manager — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.utils.pod_manager

+

Launches PODs.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + + + + + + + + + + +

PodPhase

Possible pod phases.

PodOperatorHookProtocol

Protocol to define methods relied upon by KubernetesPodOperator.

PodLoggingStatus

Return the status of the pod and last log time when exiting from fetch_container_logs.

PodManager

Create, monitor, and otherwise interact with Kubernetes pods for use with the KubernetesPodOperator.

OnFinishAction

Action to take when the pod finishes.

+
+
+

Functions

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + +

should_retry_start_pod(exception)

Check if an Exception indicates a transient error and warrants retrying.

get_container_status(pod, container_name)

Retrieve container status.

container_is_running(pod, container_name)

Examine V1Pod pod to determine whether container_name is running.

container_is_completed(pod, container_name)

Examine V1Pod pod to determine whether container_name is completed.

container_is_succeeded(pod, container_name)

Examine V1Pod pod to determine whether container_name is completed and succeeded.

container_is_terminated(pod, container_name)

Examine V1Pod pod to determine whether container_name is terminated.

get_container_termination_message(pod, container_name)

+
+
+exception airflow.providers.cncf.kubernetes.utils.pod_manager.PodLaunchFailedException[source]
+

Bases: airflow.exceptions.AirflowException

+

When pod launching fails in KubernetesPodOperator.

+
+ +
+
+airflow.providers.cncf.kubernetes.utils.pod_manager.should_retry_start_pod(exception)[source]
+

Check if an Exception indicates a transient error and warrants retrying.

+
+
+
+ +
+
+class airflow.providers.cncf.kubernetes.utils.pod_manager.PodPhase[source]
+

Possible pod phases.

+

See https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase.

+
+
+PENDING = 'Pending'[source]
+
+ +
+
+RUNNING = 'Running'[source]
+
+ +
+
+FAILED = 'Failed'[source]
+
+ +
+
+SUCCEEDED = 'Succeeded'[source]
+
+ +
+
+terminal_states[source]
+
+ +
+ +
+
+class airflow.providers.cncf.kubernetes.utils.pod_manager.PodOperatorHookProtocol[source]
+

Bases: Protocol

+

Protocol to define methods relied upon by KubernetesPodOperator.

+

Subclasses of KubernetesPodOperator, such as GKEStartPodOperator, may use +hooks that don’t extend KubernetesHook. We use this protocol to document the +methods used by KPO and ensure that these methods exist on such other hooks.

+
+
+property core_v1_client: kubernetes.client.CoreV1Api[source]
+

Get authenticated client object.

+
+
+
+ +
+
+property is_in_cluster: bool[source]
+

Expose whether the hook is configured with load_incluster_config or not.

+
+
+
+ +
+
+get_pod(name, namespace)[source]
+

Read pod object from kubernetes API.

+
+
+
+ +
+
+get_namespace()[source]
+

Return the namespace that defined in the connection.

+
+
+
+ +
+
+get_xcom_sidecar_container_image()[source]
+

Return the xcom sidecar image that defined in the connection.

+
+
+
+ +
+
+get_xcom_sidecar_container_resources()[source]
+

Return the xcom sidecar resources that defined in the connection.

+
+
+
+ +
+ +
+
+airflow.providers.cncf.kubernetes.utils.pod_manager.get_container_status(pod, container_name)[source]
+

Retrieve container status.

+
+
+
+ +
+
+airflow.providers.cncf.kubernetes.utils.pod_manager.container_is_running(pod, container_name)[source]
+

Examine V1Pod pod to determine whether container_name is running.

+

If that container is present and running, returns True. Returns False otherwise.

+
+
+
+ +
+
+airflow.providers.cncf.kubernetes.utils.pod_manager.container_is_completed(pod, container_name)[source]
+

Examine V1Pod pod to determine whether container_name is completed.

+

If that container is present and completed, returns True. Returns False otherwise.

+
+
+
+ +
+
+airflow.providers.cncf.kubernetes.utils.pod_manager.container_is_succeeded(pod, container_name)[source]
+

Examine V1Pod pod to determine whether container_name is completed and succeeded.

+

If that container is present and completed and succeeded, returns True. Returns False otherwise.

+
+
+
+ +
+
+airflow.providers.cncf.kubernetes.utils.pod_manager.container_is_terminated(pod, container_name)[source]
+

Examine V1Pod pod to determine whether container_name is terminated.

+

If that container is present and terminated, returns True. Returns False otherwise.

+
+
+
+ +
+
+airflow.providers.cncf.kubernetes.utils.pod_manager.get_container_termination_message(pod, container_name)[source]
+
+
+
+ +
+
+exception airflow.providers.cncf.kubernetes.utils.pod_manager.PodLaunchTimeoutException[source]
+

Bases: airflow.exceptions.AirflowException

+

When pod does not leave the Pending phase within specified timeout.

+
+ +
+
+exception airflow.providers.cncf.kubernetes.utils.pod_manager.PodNotFoundException[source]
+

Bases: airflow.exceptions.AirflowException

+

Expected pod does not exist in kube-api.

+
+ +
+
+class airflow.providers.cncf.kubernetes.utils.pod_manager.PodLoggingStatus[source]
+

Return the status of the pod and last log time when exiting from fetch_container_logs.

+
+
+running: bool[source]
+
+ +
+
+last_log_time: pendulum.DateTime | None[source]
+
+ +
+ +
+
+class airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager(kube_client, callbacks=None, progress_callback=None)[source]
+

Bases: airflow.utils.log.logging_mixin.LoggingMixin

+

Create, monitor, and otherwise interact with Kubernetes pods for use with the KubernetesPodOperator.

+
+
+
+
+run_pod_async(pod, **kwargs)[source]
+

Run POD asynchronously.

+
+
+
+ +
+
+delete_pod(pod)[source]
+

Delete POD.

+
+
+
+ +
+
+create_pod(pod)[source]
+

Launch the pod asynchronously.

+
+
+
+ +
+
+await_pod_start(pod, startup_timeout=120, startup_check_interval=1)[source]
+

Wait for the pod to reach phase other than Pending.

+
+
Parameters
+
    +
  • pod (kubernetes.client.models.v1_pod.V1Pod) –

  • +
  • startup_timeout (int) – Timeout (in seconds) for startup of the pod +(if pod is pending for too long, fails task)

  • +
  • startup_check_interval (int) – Interval (in seconds) between checks

  • +
+
+
Returns
+

+
+
Return type
+

None

+
+
+
+ +
+
+follow_container_logs(pod, container_name)[source]
+
+
+
+ +
+
+await_container_completion(pod, container_name)[source]
+

Wait for the given container in the given pod to be completed.

+
+
Parameters
+
    +
  • pod (kubernetes.client.models.v1_pod.V1Pod) – pod spec that will be monitored

  • +
  • container_name (str) – name of the container within the pod to monitor

  • +
+
+
+
+ +
+
+await_pod_completion(pod, istio_enabled=False, container_name='base')[source]
+

Monitor a pod and return the final state.

+
+
Parameters
+
    +
  • istio_enabled (bool) – whether istio is enabled in the namespace

  • +
  • pod (kubernetes.client.models.v1_pod.V1Pod) – pod spec that will be monitored

  • +
  • container_name (str) – name of the container within the pod

  • +
+
+
Returns
+

tuple[State, str | None]

+
+
Return type
+

kubernetes.client.models.v1_pod.V1Pod

+
+
+
+ +
+
+parse_log_line(line)[source]
+

Parse K8s log line and returns the final state.

+
+
Parameters
+

line (str) – k8s log line

+
+
Returns
+

timestamp and log message

+
+
Return type
+

tuple[pendulum.DateTime | None, str]

+
+
+
+ +
+
+container_is_running(pod, container_name)[source]
+

Read pod and checks if container is running.

+
+
+
+ +
+
+container_is_terminated(pod, container_name)[source]
+

Read pod and checks if container is terminated.

+
+
+
+ +
+
+read_pod_logs(pod, container_name, tail_lines=None, timestamps=False, since_seconds=None, follow=True, post_termination_timeout=120, **kwargs)[source]
+

Read log from the POD.

+
+
+
+ +
+
+get_container_names(pod)[source]
+

Return container names from the POD except for the airflow-xcom-sidecar container.

+
+
+
+ +
+
+read_pod_events(pod)[source]
+

Read events from the POD.

+
+
+
+ +
+
+read_pod(pod)[source]
+

Read POD information.

+
+
+
+ +
+
+await_xcom_sidecar_container_start(pod)[source]
+
+
+
+ +
+
+extract_xcom(pod)[source]
+

Retrieve XCom value and kill xcom sidecar container.

+
+
+
+ +
+
+extract_xcom_json(pod)[source]
+

Retrieve XCom value and also check if xcom json is valid.

+
+
+
+ +
+
+extract_xcom_kill(pod)[source]
+

Kill xcom sidecar container.

+
+
+
+ +
+ +
+
+class airflow.providers.cncf.kubernetes.utils.pod_manager.OnFinishAction[source]
+

Bases: str, enum.Enum

+

Action to take when the pod finishes.

+
+
+KEEP_POD = 'keep_pod'[source]
+
+ +
+
+DELETE_POD = 'delete_pod'[source]
+
+ +
+
+DELETE_SUCCEEDED_POD = 'delete_succeeded_pod'[source]
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/xcom_sidecar/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/xcom_sidecar/index.html new file mode 100644 index 00000000000..d8d9db0e9f9 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/airflow/providers/cncf/kubernetes/utils/xcom_sidecar/index.html @@ -0,0 +1,987 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.utils.xcom_sidecar — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.cncf.kubernetes.utils.xcom_sidecar

+

Attach a sidecar container that blocks the pod from completing until Airflow pulls result data.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

PodDefaults

Static defaults for Pods.

+
+
+

Functions

+ ++++ + + + + + +

add_xcom_sidecar(pod, *[, sidecar_container_image, ...])

Add sidecar.

+
+
+class airflow.providers.cncf.kubernetes.utils.xcom_sidecar.PodDefaults[source]
+

Static defaults for Pods.

+
+
+XCOM_MOUNT_PATH = '/airflow/xcom'[source]
+
+ +
+
+SIDECAR_CONTAINER_NAME = 'airflow-xcom-sidecar'[source]
+
+ +
+
+XCOM_CMD = 'trap "exit 0" INT; while true; do sleep 1; done;'[source]
+
+ +
+
+VOLUME_MOUNT[source]
+
+ +
+
+VOLUME[source]
+
+ +
+
+SIDECAR_CONTAINER[source]
+
+ +
+ +
+
+airflow.providers.cncf.kubernetes.utils.xcom_sidecar.add_xcom_sidecar(pod, *, sidecar_container_image=None, sidecar_container_resources=None)[source]
+

Add sidecar.

+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes/index.html new file mode 100644 index 00000000000..69744a2f5e0 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes/index.html @@ -0,0 +1,995 @@ + + + + + + + + + + + + tests.system.providers.cncf.kubernetes.example_kubernetes — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

tests.system.providers.cncf.kubernetes.example_kubernetes

+

This is an example dag for using the KubernetesPodOperator.

+
+

Module Contents

+
+
+tests.system.providers.cncf.kubernetes.example_kubernetes.secret_file[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes.secret_env[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes.secret_all_keys[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes.volume_mount[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes.configmaps[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes.volume[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes.port[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes.init_container_volume_mounts[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes.init_environments[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes.init_container[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes.affinity[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes.tolerations[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes.ENV_ID[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes.DAG_ID = 'example_kubernetes_operator'[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes.k[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes.test_run[source]
+
+ +
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_async/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_async/index.html new file mode 100644 index 00000000000..3a2fd7d0636 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_async/index.html @@ -0,0 +1,995 @@ + + + + + + + + + + + + tests.system.providers.cncf.kubernetes.example_kubernetes_async — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

tests.system.providers.cncf.kubernetes.example_kubernetes_async

+

This is an example dag for using the KubernetesPodOperator.

+
+

Module Contents

+
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_async.secret_file[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_async.secret_env[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_async.secret_all_keys[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_async.volume_mount[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_async.configmaps[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_async.volume[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_async.port[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_async.init_container_volume_mounts[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_async.init_environments[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_async.init_container[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_async.affinity[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_async.tolerations[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_async.ENV_ID[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_async.DAG_ID = 'example_kubernetes_operator_async'[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_async.k[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_async.test_run[source]
+
+ +
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_decorator/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_decorator/index.html new file mode 100644 index 00000000000..9ffde3dc993 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_decorator/index.html @@ -0,0 +1,942 @@ + + + + + + + + + + + + tests.system.providers.cncf.kubernetes.example_kubernetes_decorator — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

tests.system.providers.cncf.kubernetes.example_kubernetes_decorator

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + +

execute_in_k8s_pod()

+
+
+

Attributes

+ ++++ + + + + + +

test_run

+
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_decorator.execute_in_k8s_pod()[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_decorator.test_run[source]
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_job/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_job/index.html new file mode 100644 index 00000000000..cafdd343dee --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_job/index.html @@ -0,0 +1,935 @@ + + + + + + + + + + + + tests.system.providers.cncf.kubernetes.example_kubernetes_job — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

tests.system.providers.cncf.kubernetes.example_kubernetes_job

+

This is an example dag for using the KubernetesJobOperator.

+
+

Module Contents

+
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_job.ENV_ID[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_job.DAG_ID = 'example_kubernetes_job_operator'[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_job.JOB_NAME = 'test-pi'[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_job.JOB_NAMESPACE = 'default'[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_job.k8s_job[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_job.test_run[source]
+
+ +
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_resource/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_resource/index.html new file mode 100644 index 00000000000..0cdb456425c --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_resource/index.html @@ -0,0 +1,938 @@ + + + + + + + + + + + + tests.system.providers.cncf.kubernetes.example_kubernetes_resource — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

tests.system.providers.cncf.kubernetes.example_kubernetes_resource

+

This is an example DAG which uses KubernetesCreateResourceOperator and KubernetesDeleteResourceOperator. +In this example, we create two tasks which execute sequentially. +The first task is to create a PVC on Kubernetes cluster. +and the second task is to delete the PVC.

+
+

Module Contents

+
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_resource.pvc_name = 'toto'[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_resource.pvc_conf[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_resource.ENV_ID[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_resource.DAG_ID = 'example_kubernetes_resource_operator'[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_resource.t1[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_kubernetes_resource.test_run[source]
+
+ +
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_spark_kubernetes/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_spark_kubernetes/index.html new file mode 100644 index 00000000000..59c1438267a --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/example_spark_kubernetes/index.html @@ -0,0 +1,928 @@ + + + + + + + + + + + + tests.system.providers.cncf.kubernetes.example_spark_kubernetes — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

tests.system.providers.cncf.kubernetes.example_spark_kubernetes

+

This is an example DAG which uses SparkKubernetesOperator and SparkKubernetesSensor. +In this example, we create two tasks which execute sequentially. +The first task is to submit sparkApplication on Kubernetes cluster(the example uses spark-pi application). +and the second task is to check the final state of the sparkApplication that submitted in the first state.

+

Spark-on-k8s operator is required to be already installed on Kubernetes +https://github.com/GoogleCloudPlatform/spark-on-k8s-operator

+
+

Module Contents

+
+
+tests.system.providers.cncf.kubernetes.example_spark_kubernetes.ENV_ID[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_spark_kubernetes.DAG_ID = 'spark_pi'[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_spark_kubernetes.pi_example_path[source]
+
+ +
+
+tests.system.providers.cncf.kubernetes.example_spark_kubernetes.test_run[source]
+
+ +
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/index.html new file mode 100644 index 00000000000..e9bb0d40559 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_api/tests/system/providers/cncf/kubernetes/index.html @@ -0,0 +1,904 @@ + + + + + + + + + + + + tests.system.providers.cncf.kubernetes — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_images/arch-diag-kubernetes.png b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_images/arch-diag-kubernetes.png new file mode 100644 index 0000000000000000000000000000000000000000..1bbbc9888e510011811f2792a7be15a54375494c GIT binary patch literal 21804 zcmeFYbySq^_Bc9s&)$1JXlW>3C#55WKp@wZmE?3F5JDIP za@mF$9DsbSA*2HTT(N$p{tN;sizYjLNeF)5wNTPghd{jVLm+{{5Xdn&6u1n5xIctI zR$o9MVo4APty5~PwgfnF*<4jo4ssC|-O~hqkvJ(Cx4Vi;L^q7_9p6R_AUvH3JKI=)J5!wG-nmhJtWR~-?X5p2O+Tr-cmKSqq zC(rA&zsw7b@|>TJ^@Vg=VhgGjy4~ID#ML+K_3dNK^>5e5UrRBMc>DCSf&CRey$3sA zV%*L%*jAQpq;hurw9rvL;} zDyqc|fxIUF|A+s`gh8QdSF_-(iC~o=>W0~D8vhe{NHasl!+poZ@KfK7M`&SqAB+M6 zx3Xs-0p-^G6XR`<3xQ+HasHV&FM7pqF@1!P-&b>SgGI368I@R=c-l%IFi7*oVe+)H z$H!#P#PqN$=zc$fE=wgOP24Y6<*L1!2xE2yvrh@MD*eJ}P{l(`)PAzY65x~N=z?cL zA%Q`d;pIe9F^L3x-~2k~pSte+4tyhcOUwI3y zoUu)vwleiIi$ec!CrcL7{mgm^&b~#RT}i5!Aa|Ps1{*qZPu^iaJ5sDu)sJG=lqHmOS@Oed*P0fhQ94aG?Tx+BL+zm6W+Bz>2Juajo-lmsWfQv*$AU_=0?L9IrP)CL@REDi2A)=zS9)rVlxUmW~|UiuKA(% z3_!hRsoI!SIjVMM_al2dz`0GXO+*11jd}){n0Lq9a|OfwOzbo~>^sD?XHvtV5@&m= zh>8hi?$+UsaJsKu$f>5iLh6D9k5&!T-v-9g&kU{eF$4)&p@12K9LNR}lSjv9vRZo=B<=0E^By6^|pBK>IMRxBJqZ| zmFOMA)p0(=-PgfC);VJ9&WX=H->2FxA+lT=9Gjb0>)R=m zS50%7v&hw?XdOEp3;m;zE>r$swGa}maUVUKlI+ss7gKp>S| zfM;cA`0iwTf;rOQb(ULpeGqaup|RT@*8?A!NYHAO$?TK+r4UJ7ILtbh_t}#w6Sw*O zP#`i%C*r5hm5e->vAI9~B?cL+BDm)-KXn!#lACU1JAgF~SEK1m$;GJ* zIq`RDb(Z+J`-; zl8sSXFo+;P?4A60lSmf3@{{!N-WT0;{PcLO!$UI`8@Gg1g)5mX#_=poVu>{OBnnga z*lKIHd8y6A%;)cFt&7>F70KkZe1tQ0w^b0;<+%~m4dF=Kbw{gzzCdz6;|(<>QU)SX z*}%$jUkMhu+|3B0dLgA{B@}gVNh&=1l|!o5)KlI&@fuVs4(C2}l+7hLXyb32A5LSX zPe0f$$6w;z{-{6~w|8`drz=vzMuYkN;_KaKwD0HzxbH-b+?t=z2J#Fzy+(TBbGAYd zv_EstX0`a@79*j7nV8Kd1u6v4X1w(q^W7a!{~2LxDaqqB_tGSe8EqEJWo{%r#Qkg| z6~h%aw(xvtuac)@Dbe2XrigPsbe$QUC-|sEQ0*ndQ(%V3)7?3G^X{Rdc2KF!c*1kn z!E}@mxznaYqIW=#|XH)SgH9N!rkdKGNCsvO=8<58-r%K zt{C^OJj7(s#Os}XfzgkcuD*r&tSGz!LTU7u;QAJCD>KzQDhYJ!E=iYiUzeRtfv8pT zn6$w?ig8wm8`Zas#mPa_2&${C?(n>EYQaEU-1 zlgT-8;>Im~b~&z)fKb8FO+A(uK=KDYlCf!RJKhkLg7*7M@H`Jg)+~ea!t-5WsCgfa z^-5;~uGvE|_YJ+O3U95>IAYoFi^2Q{pAIrO;pER^zKt!$;Ggktg=q`daOziRldl~I*3M0S#YnLiNLM6t2@i)qIB!Jcw{{-cNZgnz4=BJj@t`ri&N_q51R z%$KiN*OT4~?#-Lbka}=`H2W&N!{KXRtskuik-1fS*#v)|xfb^mh!*~!OwMF?a#TH4 zLG}>_eQNv?SKz-aeUth9JD;((KGpfRb9+p0}5`8|-j zK?uefQInr(;Ac`a2-Hpa^%?(N$Eacaw0Y5uWt+RGBBol7K4Sytl>rWGOM@;kk#@?+ zy%^%D>uodYa|F)6p8|d@bq4zfeWGrV7oIeT2va|`d@1p`Pqx$Z*@DGJ$Hq!P-auo} zn^irFW&S9>JBBJOMzY)!>z{Sl%T*s}aqFrX9@jyHGER$V0D+|t!_ZDiK)jNZJeo8A5H6>L;AlDE&pPx51v8vni<5)l@U ztcN`XoQG>za4V=?Hqwv0(!qjA=3n*PHt`jb8E~8T)8Q`t4PJ_TmEeWY;p<-Wanna> z8=eOr(FSDYzwr8ED(7LO7V5CW@G)JA-HNXlda{7C?)z-JscJ(VVLw+oxdHfB?q!3j z(k4XO35le79;+Ryb>?)YPn@0u?*!@-gsQA5^g^(r_c zDT7`a&XRe1ZLs0}1n9NxREQJNiZqn8(jt8xYJ9o}}RbObN zu$=aUM`XvfXH_=awg}XGE^donN?mB~w}I!E`C={W*FMumpJT{o>##Q)w09fK9E(Vz6{tsi;q;l(x<@brmOBL zjMdyLJXqZOzRU6!M$wmxi#1s)c&enJpR7Oi z@wgStlv3~^oENR0k}giMY{2y>{6S)sH2L zlR;>OvlBw)m3E7-4|ec6c2rMIL>aw3wywa>=u{|sM@J%l=0c4YyU0)IX~IQTVIr+b z-sd7@Xn!(5jeH^m!i~QFtC@r`Tp1YqMRPf8mWg?k)P3GDITqG7I?M1n%mC#Blm7O{ zw-Xq>Og=bhp)rLEWywBag8d*X**_ir;^PbHfxso7EbeOr`iQwk|I6_mxGgdV+k}hG6{hTzdH?}T4{1ZaVruTuEUR(veUyEc~O$Sl) zwLjkY|0!VXAdRQu0%|ekxK|e~3v?sv4eZBpS>~ol~Po`K3&UGmlzKJ(~d{KGa1+ zChYe|x%rgM@~+g2@auW@3P8S>EmJWzSqHV%C)B%%vwjA2KaBhRg@m!4Qot=O*9u#y zWjCYR7XlTj#S%G8PdpmyE4Gh6x@-%>l$#4#N`+Tfb4thps>{o(2KU`=E4FF1J*`~4 z91I&X>sl}PWk>2bB4T$nIjcIk2eV3y?ecE0N(?broFU?;OF8^N!q^rgu+ODzaO-I% z^gMB!XpVl3>#K{&Pc+I!bnS&nPEeVLu;fJg$w3PVo1yfBCs$#_wlt1}=M znH2rC-bZJcvaCxn4Piwu| zNc=`tM37|e+|Ma1hV`wXXSQmvu}2UDEdwMbtzv%fUZNP!ad?WF$~usku_+@&hR}+? zAvlq(T%)-J4}onCj^2c4Vf2?sEAQELmt{zP?W_r4Rx6$9UECag+kufmu;XO`Exg2j z-QF5hc>b6VUQs)Kr(vz?8hjzU_{|&vi&8>-R`Ur$-mw*w0vH8K-3TPDG574r#sON~ z0boo?v8EX&V+X-}zJDhbLs!@Y{S%Ndk7lgbC0{8q#GF0gK!@rO|A{^+*7`ZTldtd_ z4qZIJbea7*(sjBy19ZVw&)6;@;+w!@LFBhizWu+e(bTo%r{<+4%u zZ5|TI0m;4YBKI&8cRR`_?y!0KuHqE}c;wG&#Si~X z)Q;Iwptt)GAQwJC43yv_&9%cmEGD-XNvLK-6XHL3H~;bX(tFqU(rjqz)q}`LjNkoh zRd2AT%(&~m8^0+FykP#s_U#hd zf2|s(*C=gV`@QO-YHx;)Mg1`XJ?MtobU600n1mbb5ovM1q59YM;yAwz;kyQOF=Sh+ zFSRuQOLLClLjGmm31kVDLAJX z8>xuDwz7$BCb*FBUkmZANdrMe&j7b2=|UmUT!&~3E#U_GwpJsI3d3(cTx%Oe>b?5tK#s2toat&_(V^CQi{NCc(hN#AQiN=yaLo_`o8*8PxA*TMOib%%-sd*dnaLh=XY&p;S+*2@vw z!MI1Ft(4s%NR{=Td$F;ykInpfCtsv$aX+W{hpLZo_Bxv0p}G9;>wZhHOOpsRwKCR# zWWD4@#RF-dhD;h(5&c!gM`5rQZ%{E?X>j{qyYq%894vKx(hh8)9cO-gUE*+dU_9-! zdgO#1dnFn!!)PsmZ}tU9(;Ph(?jjJxTw;B%?R1V#QX+QM$OJvUyW1o`Om^Ad z<*=h~*a00;Wkzo=g74t%v~Q-FK5csR>}w$iU^ajq#KdvX^P-=P>9C)0yBhM9To_0G9y(mKig z0qhR%HMSeP^Bmn(--r;MP1go5y?yW`FlZO*<308&SLGEkRFhfg$2=C96{P&Spmk`a4-MM-}eADO)am^E9 z#DBPIjb-Bt6|_?1ZhiMtT2c#tx!PK9W9x0h2M)ztRx-wKkF5?e16Wnijj=B?p}!@; z<-v%Vna-so$&KNoJ72zVhf385J)5}%C!CR$5Pj#9+dUTq^Ay`)asoXKh!z~t!mIvk zYqcUNy79_?mj1sxL0*JQ@bZ1(`Kyz1k}U*gwjBjq2sfqo%)Rl*jX02YGK5<54=K~y z+^(JiBGRMG8{fh?bP#*&n+WW*Gp(8re*L8Q#nc=-@g>ifZB(3?zYs?}uN=}JusfU4$Bs}X$f`+RBe zdb7;kyMNJ|W#Vd`2zUz3Eeqxy3*B|EB+3yIh18Y)`mp;OzW!BLl-EdKEeO_f(EJCy zw;P(yMKD41a_udUbruntAc)m1N`M6f*X=@%_MmGjW!t6?L z@tgR|4};hc=-p_x@Sjs{;)$oOXs(~kcTh(9smS=`&XS1Db>4Ra zFCRe+&w$9LAG&7OkehFI<6$c$%5Cet7s|kwA48k^cK(|JxL+r>Qt)1FW{6Y|C1#uh z)8@nBV&KgyXKQbyG&7vSrQ*Z9dByMns;~0XkpAsMLh=$^OQ$;Da2K^1>Yji#9O&2+ zR_%O`fsuMm9jfSv@dri2>_AyjeAfdWHFX|nvi2hD4L^wG4cWmZjYe5NxX=$Y`2WNt z>vHDZ&{^_-o0=>{-t~GprfP~yGx)WQ^rOU1FRz0L?07id+^*96$4x1C9^EAnqUJX} zK#wXxe`=v9EC%PjNqM-p%)F>wBhS-|T))DYHYz z!@Hm|`ma=s9=eZI-lCzIUWo|RC2_WgtmDRQ__&@+G})xw?y z;~rR4r;65yHAO%HMvOP%ksczuaPk2ky!WBcN6ff2f&#+4(6V5kbUnj%{a8&7(7JQf zar|lZ@_3fa3$E1g+-`)PQ99S?1`2zP`f_%OHj9%wXGe)Fp990}Y%Y!zJOMeA4fS}z z3KiPIc=%HnEREI({-eh!${z}?ASig_hNH*hdq=rY-U!^}BLB>5?yPnL7nnMyrL=_C$Q~J{c0*9J zJ`cAz&E9@hsE!Kw(VtWQJS`qZSfUtvP<)F@s#Vv#*ZZS9OI_aB@7dZ;%WS`iK>t&G zve_7+4E9VGt)u_rVUchA=tp5dxV`)VyII>Y zX9c_(ZLN!a=ldowOFUDtf4Gl<3RC03o?XfQYv$?(N@h%Lpq0Ap_|!o8iGSp&#C$`# zaP>ej{N^F&h6$(n5%cDIM5)O(OU?DNqFeL;Pk*{Qa(lP_I`8LLk3 zXn$um7tEtR1AhMc=f-;qFwEX!#?bLeA>0e*HZEbhE@}L~Htib*Bcrb6SXy!lr+{Cl z1?4^Ld@w7HAzdUuhelAqr&g+cAn13he;9oRh%etBSu%8$Qtoncw2k+(jaDNV=CoAJg;rqYB|sOnVRL#uvmR7r(( zMEkLSmWci8$H7Cx**QBQ9eMrHSo||Rei>7`f8+;&GnT>A-~@eGF7+8MaZ8(*i8Wr? z`FUSiP?dhX+l`xXM&_Hg-~}~(^?>yk5d%5{~r_BXWQ9(fz+b1D`f#_; z;`xQWim~Gl605ea&ooS$0`?p4^p+Bh1mWxS$}q2CpN z`qaTh^o4)C8FBlP;UA*quDe8g(6WVyFEoxs7xGl7fz{bu9k)lk*p&M+l_Kywc1xM) z=C#dS2TkV3+8BK?wuMaGotGxw?j>`L)PJo`J=%yEZekkVN}?;qcE@B`dcRg^K^Yxs zXKL#xpj*`s7Hi$q7f`v!?G*-Orc;IX#W)9>jxRMH`)SVl1i3vP_4cpb7x03$Lx=2q zt9|E;nDIlQ`S`YN4=~pW?yJtPzl&Lo#e=7q^S-~9K+`XJO!-pG-f^j+LxZgdxg}~+PF^T`qKU6 z$3liKFn2hh3(Lu+da$^JuEKh^8Af_cOn>nT@%ml%MgK85x^X@#5A)mNM;!G}Mj62V zOL)zZ=+SGkOUf(vzJ|Wm8J87$HJ}q7HJ-l|nJ^q}<`6G>>Sk7~ch*#_@~QRp>E#ug zTl_}nugzFqsQOtL*2L@3d&hsE6GmSbD)E%R9y{8Al}XU!_W^KG8qLMe+>=?kt#RBI zqbNtAk?a{sn7!E@W$TlzUsnj;gue3cHS>JJ#|+V zfOzq#F7(YbGvqb21L1I0*#=7pPf{0}cRpN^Rl9J{EoJ;x=jcZZQ~y3+>LoF&dr)># zj@HS1T0chQK!UG}h98Y}jdr<3$G~~TDx`IprF`+nvUj3C}E5wF5yO@lf=TNGnNe`Z4Q@7;W?Um^) z=B`^-p9|=|sfL9dD*&r&J&R;S@Tu_knANUOHADUM#e7_Hxb1mobx^k5S*{}&`~qDy zwAzJAFk4O>=#TczVO&XVRSAhT=MH~o>|JQYs0vv8v`^BMAKHnZq%1;C;^wC!2sb;b zUP+#){){#ozrwGPhl_=Ej7OdpVqh9@#^@{P&=)l@^&ih13P(nqh;i}lNk}aIv&>Mz zSHvAvsRq=ED?5w(PWSd)YDUJZjo3Ks2mSCK>W{I4?EG8@Z<$o1-GT4!1))YCdq|cm zK8wq+7q)u(8JO|Ck#1zitDAh*T5IHDGgwy!Lh5{$>BR7b2Rg{fdN(b*Mcg_aLg?C- zM7tPM4<@;8oMy(oEU0+Y$~$s`=40G3yXe#+|Na-T-XJ#H+}6l~;Dn}IqIa4M&+ z7GcK6U6)l>1i83pWST=AV7yn+L#G<52Mpx!DQ1KaLn;QAQ6=X4vB81LAQ|4Zs|JYA zFByJ_KP0l;)7n{w- zVD9{@!{Hl%7QDd-V^N2L8xz23nOlVmB%=os+ zQP&)9dFS|ju@tIZ6quJ1_V#5p{3}I5{Lvhq6F%3jXdg!E^!SQcV`Lt^bje^lZ-epo z<)e;CJ)od4r^d)_hi&R^WAtToXiyBScO|R$@#`$Kq+^TtIEaVfod)4%u~g;qm%0#t z{t{Ur@I@|E64l8`4dXmXFPVVe!PMSutnRlcgKcgWiS{aewkB8}J7` z3kKjUNHZyPw+Tf}J`L{9jy3`&cN8S#@^R%%wy|dsz+^f2=JDJsPs2hBuAlLtULpo{ zGsyYG-E(00G8JYxA^ru}c+$YY`29Un_S20v=*Ad1yrJ&c);cZD;kLc2H!;`LVeoi$ zxWNHyi7x*6dup)R0NSDiJcbb)SCA=LeJrlwoh+a7M7Xmo!F$*E%kAFE%WimJ28%YI zD%5CyO=;9O1wt1mgen3)Qj1CAz$lcB3vF6yH5KrK=r6MGEAj?&<0kHcvmce^SWTt^ zGjxj2h2k+jta}MLp-0LD=y&dNc{o&ik;}7=y_9CjiD!W4gZ!xepd zj99}B_!qVGss2Kgo83AJ!s_5#tM0^nFQwgSe*tP7Qm}}#6JfI^bl)kq% z#x}$;FrL+&fPg1$Vdt>#;D%U5N1|8aQS&#eK1aDQrFtiT1&DD_%s0_e8{uth&tEU3 zb7n!w|2_za*w9jQ%1tBU``_otPXXwYUt0L#78u5X z4P@Ixi<{^P_$v5wo|!%Sb)+M|PV9Xt^VGj%b^ zqBf}Myu10qH~u68mxL?E)CYb^QCJvs7TU(fhNXy$PkP$Mld#|!U4E(kLtzljWo*$+ zl`7RUs4A_L(e{`-YfOfsbJ_7qfx*<+*oLaE2AUc)fv3104$2ZFUkt@E3c&63$O3X z#4f#n)imW|=9rPBltKz&DWL2dX6?XB!CcMsJ|ljM-R3zG;ElG= z?M^R=%$HNMvyuacTnulqtFOc)^w99VGB*nn%w&6uvZ}H*l%(*R@Nv* zmT}=W0xWc5!0V9XJ3)wTmqYwUEE3LQg(cQYrAw4%@fkd3P1t$!^y^%6ybtJ3fb9(IX=9f^WAldAcemjBRUWMFeD>PNtfi}u(lE)jM;jGiyQ$;Sb55LZny7_dkmdE;U11fCCW{9UOAizD-a)Ce?9 zNqCS%riVs9<_;*myVQ>zADLf)UninKL!k*%8D8$>@b&PmxrM^B(SdNBPO%$;1HJll zc+^TaO?@3F(M>2dM?NMrF{6CoI8d|eIWM}O`G9SE<^eDEX)5;pB-84|VNx^fwS7bKGbnUUtLayAV7h>u z1`Z%bGZ8jp>Uq!+yrpLq27Vt6_hd_+M(C?Y7isGHAkkZG^NIaEc1=tt;?O@8NBg~!ETnwDAi?yBe2}?90Rn0-obPU*`YX zY4!2RIj<`Z$e?aj31w5^$(4#5#ESFqbtBzA`p_2~ePYf1*2Nvj9={-oHm?IBo`juh zP0w(t)xJ8We{R7UI?F&ZYrli;FL>w1*y8?4*8>*sKN4GA+a)(-gP=nR;8Tb9h*>73 z*HL@^r&}{8TbR6bbfecGc|r1W*GoB#gjo##H@ zl;Bw=fS*CM?9>=IW~Sa%mHnyw1_mMbEQ98h`sOZmbb40((Mu*Skbyn6!;eX^&l7Zv zw~_8`6VGE@kdwB)5@!Cr?!FN1y!t`VZY&c+uq}IC%L4%4Oe^__O;4F}Rz~?}vb3`VD2_ z(ElQgc};)@L&pp9nTex-pxaxWx2Jfuk!aq&c8bMd9$dv<2uvD+p`-dE9l2bbLWuD4 zW2nSr(Ep6`7@!19lC*TW80iwUY{jPTt#6hbZdFKX&`2l2wuGS-t;5A=%6D5fc-Z^4 zHmCv|6ldAZKeA-_A%9aW*!mu;SuF`DCL)B;{Y)si64=Yqb%4o5u`F4&!co;z{I@J}pF zd@`vqBhyChJvjrrRG4QUPkGLN*F2sUCXvTC0sB97vP~-c50ty3PS7_%mI*M&m!yXM z6h#ndvMItJ);E5Y@JWfxRbeNMQW9$K*)Fb~0Hu8O;~Vi|(;z=BEtsxspM-w*8Ryh+ zgi%uCBd2w2L(~cMhbowKmTu`GDw-@GhD3Bc&%ihS)k=9OUqkJP^9-q%tuJW#^F02{ zpe_PIqZ#q*h}mJZK&SisPX;T{sb3=sN=gntn-th4SgI38;#{=w@dgKC8{%NDU7)3& z4gGdE4|eb*I@-kBgkk2J*hVhw{4^xcPXu#G?gHi>o+h0V@UtN8r~~!C}2N->|Wbkb7sn@-6cPXLe1UB*7i5G)oSPV1i}m- z8UU$bu$@!%jQ~jtbO2B5%*jsE@$II~u#d+lz`^N6MmRn{Bkb4l{BkdGdefp7p2%y= z_Ys{HD*gb{;(PehGfq3;Kz8{_RC9;VHDjONqyd)K49uVvhmFC{dVIDN=P5!C`DHtt zAi4hRP|1R;%WNYbNn9rT|58W@x76s(w%RZVSZn*;(L~Cq{MuKGxP=WYowK3+Uxq+@ zYTvyz36>K!2wetK9JwxG-d>Ia=um{F`@wXHa@*o{1CUp?#q$Di zJ}$fvI3>W;Uj3&Y4ITnrZZdG86D=-PiGD6U+e4Nh`{!I+rDogDP_=5aTOvF0RDVsZ z7OdCPMP=e9qeGux_k*ziQi$y*6s_MvY^*WEBO`;5@$x|y2>0vVA^675?yCUtxN*{bVOnN2pncMw9cjh<;$|ZEN`_@{Uuv4FZbD12(?j%E1oACx#3`8O za@wceXf@*%wA)c8x8Giqt(dMC`uOrwgM`J3W`QL6hx;=-E7!Nrc|%ob$9`)k5w4bpOzJ>r4fm&>pvP4dNKRa`IUN>b+d)(+=`~#mGAlN z1&gcsAEj)tYVQWkOBF=&w{~yC0AYFK%a++lUq2PDK6>-<-UWN!D@pQ3g9bwrts*Vv zhXKn>a_<8s4w^1f239EVM1+*~(-T-Qhgp00(b%$zeYLWS$QdX3`rCCKT1*GcJr6Hg z=WPrjt+Wn#Tc-KSVAp*?v~ECCp97tLwo?FG!;UMj=oCupqAm=zSpji%96Il~ve&jN z-*0SJaEyA_C-!}Id6U!#d~a`ZV=!x1nYV9MZOzftn#^qbsmO{r>*tGEjz^Sh4R3=R zHCfKHFQ#VBm}LtTU-8`fW{Q=vmi!U*hcK4ag)l$QyJCZ}mtu^5Ke)Dj5d586(p9(;+4Zojzxw?WuVF9(}s#HW@hL>Ls)JVlX z)GRmk%51>9_WW>ywfW&bj;k&ep4m9)-2Z$LO@7DqSFBXb!`_ z7FY9FzXoZhq1#lcd+brTr+e(%RgE;O=Jeq{w_7i?*4dhSxCxKwmduFqVZ?GSqFlw( zj@)antsHo^N-w9u0@z#ilPf8P-Sk)YM`BEK%l#8RcNbKoeC<2|!GbMuB3S|Ji;@|~ zGkKZnX9rXK$*}4c%Ztgr;(j^3i2BUJM&s(*x86MH%2*hBm-NAXlQh(xnzZ*P4KEXT zq$!~BuF-Zp5++{dD!x}IN&S86 zZjA>+ZT8#rCAg*<<>5%(123@%`-0Y`0vcU)&Owmm`WEU!KQ7iUxw+Sj9=dM3g)aXf z2!h39?T5ysH@=CSv7swvO;8mxT4~YIE$5%-@dlkB1B5irJUv$V&*H=~j$K9eqVtgf<^}%V zLVNsr!?_Nt1;dyo9reArXon8Ly_pH)65}(Yv+oqrr>z?LDq~3IHNCk4f2+jwd{UA4 zab%bJ*{kH^77Zc)RqNe{p2=L3x3GBz4yzo)7z&TVqn}|H-weplcV6HJbmkZ8eD@5Gjk1@gA zetU_FnAx1aYfmIh6~;#IX`)3MO#y`3r%aw}kw_=yU6@*H+`>TKb))kx)KRs2-V1B}_G?=L#5hnPY(1Bwecxjq|E z6fhC)R4_RC5%2BZ=%?`TdH=h?bnJC36udf2qn4oHjYKDc&wTq)upf)P3Y=Q3e9n zBh$!Q7*5~9Ix4Yl0~s?g>aJ?Ef+bi&+cmnd zoR3`BAxj;U0qkCI6>V2me-j)M`6XNMj$a8H=NWP+EfeMkK3>2$1#C%^0a9|H$UW&$ z@)Ph0XgAAO^oBJACSsiiQ(rEnAi~s!zHwnaP|CvfazZPlZkiwE@c(82Lz92H^0>*O zu++j7{{xH%jF)A?oc;?uIC61~@f+AJJMyIeaFrdH%p~IXeE}I(;LGAZi^-S_^S((99&Huxu3%&rF_-eYm8kY zJ7D`?0M);zK~*j2u?6bbC}}a5(y$~%uhDSnP>BWG&!IAL9BM+BJHM_6AEpdsF^5aj zHHAt4iJOaTXKsdmN9vOad5&cD^ImbO&W*54$qH$%JiWSiiM!L9&naKwfoD$4n=D9|zpmWdXcbO71N z=5NOkgu9(T*cKn(!!J&_XahHKYWkf9?=?VE1j4HR;-MApByS(YB=-dfoQUtZH{?rY zUMyXlUXU{$wj9bHGo3$lyG5zP?;G>*b`N%(?_+%M+vK$?P4 z{^Jj&T69c3f4TY3oo3&bW3xhNA?3rYAc*8D0W_P9vy#t!q>o3iiMOK9QR_7C&cw7< z*?Ct}h_swvvzQp?*8zc^mM%onSX$?~TiZ8ggxZfIj-5QX30Cs~lZAa>zczE}=SQC> z_$)V7x5ppm<{OR3mzXBWH$?fOVC6^HK`Jf$ex}q5US$TySLnGDQJzj(Y8WMsbhMp z5dKP=^I!ljRJ0*?lS)kT@<6i6QncmqwLBM-ma^zFTA!}{m6O5cp*-nVVNg4nJ9#HsM{UPnrSjM$%grMi)(nWh?5*8xIf%i+X$smo zkWB^fBF>#%W5jrZ6m3^oS)Pd>-13)iG&i0P`f@(#P6>o@-bJ>4bS2m>oWwThD%fu0; zJdT51uj?xeD)_|;ztjK3a8PILbyfBq-{n$i;&SodQHBymx+l2X%IC=B!Thc>*UnUJ zNlhENlzXK8$5Kjmj>(^?4e8)#({F_HTyUz=CM@G|#WW(%lp_6M2TXWN|%@v<|@EkWXZY4K_nvN2*Y+Q{ucZ%>np^kUdvg?GGMkE-zP8?AF zs$wBOnOLyc_9rq~uBx@LPRZ^ULBx;QY4w=i^kHT>=V^VZ%?5e0a~*DpjSoa6OF(T^ zuZU(TJOu&;X0o7EVsUlOjD&^B;|)nqZ6WLwf;1p ziIK{j@=7LY?88F_YZBqu!IM`I=N(J9J=y)pi&rg(!EaYrUQeRV#CKJ&`Wt%`-tu6l z`NtzJv~UsZ44EU*v%O+>O7Dmi&Jh1R*cbu+`Y(zMqS~keaK_WfiX`u7t%zPvdrDvM zxPkmLYUnd{7~Zdayf8{3 z?0(e;Yz8L1y`v7d#6dI0Qm)}^bc~JC6xu&?m4^!9_w9;w9}DS66?nND(uBe;Su`pG zpLMh1!vUfdwb}GvYKDj%j!@3)Qp=$(elYz3I_XlB&Qef|ihi8cwDYAG-$an{WB*$< z*B%aK+Qz4>Y~)brAcsvvG)RrfIOVhs8Id_KPFq4=>ELY8+E8JUkVT^yqZwm{WOAmG z9C8RVL&JnH3PT9Rs_!-WcCYV`{qOr{|C;Na>$>mfeV*s{-1qOgpZETe26U5rVUpd% zW0_qnuHL@N=$VF1*FsM-RE zD|yaZVio~yI!ICf&|fUI|$ZR5(%)u+*6lU0y1u=R%sR9*7uSo9a zFMJRXBFxnbUSa60z^Zo)hbENP`Ln8nt$nbsKH#WDY`3cNXg{YUUbdTxOFx`qjq*~+ zPOK<=e(j+*8^K6fyo8xwbDF)Mc#U0$ok>@qJFm4K|{}6F& z04bxF6*=GBm5pNrCS<7O@LZ4pwS(Rn-y2YBfl(QMi%EQ8o5e(Q)p~dj-2b*~rrQNZ zW}I>agdHK^1jDO}#Z2Fo@P!FU93;utAFbTO78YBMRBIT}$NF0)FmGLFa&A@ZXIy{+ zDyo!>j3P`bl(KYu4#+(FYg3j3Zcr|lnPZn+gOL()m?kFQq}BwI3OnSQsyM87sG`6{ zzLqPxVPnatjC6gHqd5SLCdD9af{Lw4Ia@tl9~5PO`m*V3WM#C6-y=ZzQqN0YY{+np zXhU4_);~jrfdW3m+EY&#zfa((+q+-Qrj%f6M8s)k{!Z#eL?pI@yE*olT66lw0@e)s&AERnkNGJiucZD(YQYUL z#&Uv&g#kGv|juL<9-PzkHex7G~1kTeRLSs(93X zWLKKYRXwvpeWSFg(~ES>zGbz{0=dDGgCKBK?V-n0?pzzWEm$&l7XQH>+ho3?CcuNLhEVc$0k-ZS%1vn4~Ds6jP^2L zyy)H9@etNvLi?0Ki*SsB!*o+}Jj35~&jKa1^hz`3&f6Gte62RagAp37-7pXls>qE! z&5ebv3L71hR~6uW*e3)IwQ>|%_5VLas;<~YGK#z3i@mZ#?+kS3~*8q!4WW&MW&>Ft$+Oz0OntcQsJf$Fr`AO&|cux#Q z>>(q`VeZm#73xw+8@Vz!XItIXdU~+WUeA-;DU@0aRCFa9(R}CO5`GG)Nr-fVgl~rT zS%TH10ZyK2yPi;KHjXr{=iUu1XtV6eL;;NJtPl+X&JtHakRlzP@G~ktZf$8WR|V18 z%n?Hdl4Fr#ivX?g!k<^fF+Qja5Bp3M`eXx6L!lefV`9t!Jiv|IIc* zbB2J)N$TF4XBArfk6(hAI__{U1Ez5Ic)s>Dlu>R{`(CFnN8OUncH=S@!JG|>>wt-- ztA6oyERJG6Ur<;Zp*lo7T&(^&K}vV74!0h~XW9<7`pG*tdh`%N!#e(65rb6lE`!3# z&?e|zvnP`F7lvqb@-BsAIX@@#id*pHME2Gy!X#pFrWXZijj$F%>j!8HCVKi6M z)yxY2KQdE_mdquW2~cXy60l-uH@yGgq`Ke?ZzRm>Fh%j?*WvkWdzB(M1sZp#d_I#d z?$=k-7hL@Z6R-eQHFl!a{EUW;^_sknNbTFqF0&CTTE2wFpS|b!(g%Wi>DFi9ysCoy zZTu)l8L-ve$UrSjNW3UPDc7yN8U(ut*tw3V41JZ67Buf%gHA@ zvVsK!!1?Vj-_B!~)A#lFg@iTaY1b&iK+Nlx<0v!cSaqh{h#_K%;4P6{1Tc?8l()xz zbrIlE-i1c1pSAmfqV`n%`CP{_eJZQ2JWdhGLdSN!HRu9-eP3HUL z<%LkCKBOzp#-@}?q=Tnh-j!CLwp<*Ki@hfj;sZ-vj`;Nrt$L0t$fY7!|6%WjNYyZU zhnD4~`4^#z0*t57*$t(tOnk?pfW`zyF_yt^*1kV22m{StC9!#b@e?-zKWPdh!vg+n zJQS>sy*i($_GHs^K^%a_-DdLc4U$@+c>`Tz8#~hmC$nI?S`ndH%9Y{g3{nNJ;+cyb;U-4lo2CGZUevj;mTDB2T!R3W#K-KQ^3Ud;fJGw#adzz;L=W#0#Y0U^RzX~Ye& zs%GiI2tg$IqRc3-m8t&g`8Qmpmq&m1TJz&Q8w@Eb3-@XzEHJC6!|7-m*$&HNTu3e0 zw!xS{5;zv4wcjhzV(8%f7{Z9B4uI-zRin8~gv9%DRre2d8kzJ?YsxX$6s%O~a-?*f7f-#8 z{KUoIB9cKqJaR+ZiK_J4JN-IUn#wHIxa`UYb}SeenM?Nnd9l%0fJY+0eO_P7oEYm7`e`zEp!dS%^9C-5>1jkLHE z7Z-ln5db;yF&J=g4TY?pzB1AvR;7QY0LFG?0#Bm#PDqE&L4~e#VT)OJl_^Y@ z(jiP2#jC!#ZK=-O5~m6<5I53)QF z$wGwdx?f4C5r12|6hfMKuKE5Xu*6a^=SaerlbLut%PGe=T<2YCdq!{8`K z=zk*I=1shO=u_0tjH+IgJ_ccbNp%m%@{hHJfH7%0uE%!Bk~i(46>j@5g~lE|f~1Kp{p9YM zkIJ83p~^sh+``10It`YyzdYEoY|M;$?|hRcRb@4uSjaB#Hahi63|nS-RQ8296R%|A z@zl3;?q%h(ReM~}7CTW1u$}6*1iTg^FY}KAbN`?__iy-n@|#Fyrsz3Yrm#1t)u|e6 z=^T9iY_K=NE6^MKf#~Y!>Ogf)K#%I9bafHO^bxu+O&uMCjt=!ivBLit1YADv=M(YI V1|08Q`Je&B#?sz`ZuZOd{{S1#=}Q0r literal 0 HcmV?d00001 diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_images/arch-diag-kubernetes2.png b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_images/arch-diag-kubernetes2.png new file mode 100644 index 0000000000000000000000000000000000000000..acaaf430e914b5bf121657731542c4bbb4e89166 GIT binary patch literal 86384 zcmeEu_ghn26K)h05GfuN6r?Cc0Ra(0?+Qp)klv&>X%bqHqN1o&DI&dt5PI(@2q-Ot zD!oH!2}%i_yEdG2zVH46_qjiOIgigt*?X_GX3e}aYvvu^KT?$^KTmre27{3+Jba)I zgPpU1!HD)r&Vg_85PFxv|IS!Rt4PCOMWJN-CTGECCbNg?Dliz54F>b`hrxEiSAJL+ z%=In|w)7MR6Zs5-(Ky9dKNbT&oHJFDe*imz{!6aQiU8k`Iz7~Nfx)iELH|xExW0}A zUlJn}RAh-~Nv>U?WHx)A+X9{lQ+Oc##AA46%+n)sv+C$K`p(ejF#oXc$zK!#$xf$m zAs;0((e@GP3@d(P(aLL+&Y85y-VBH=lMO9K6tH@A&l<=Fk7nd)PUq^i%(QxC^^M{?B{A zQzSs7lJCJHI!1LV60!eunBli2eHcuJi0}&Lmp^GlHU9M0{~Y#L zTg2ZH3<-G>1FCm`GAC*e8MP}Lx7mwI-8@LSC{iQID18dnP3v?2B#27Z|0D5bAeE-= ziN?a87kSw9`whlkdJV>$vTx%`XETK|dZf2NxBrQh*4iYuo-FweL<*8x>1k*z z^mwZ!shfMm98Q#8HI(eJL@a`k^vplO7vg7Z!WHDRnHY+un0ebJ1HJu5n*((0^D(}R zg3RDxf!z!k?CI@)ul_QQ>sc?*#Aa)AR$uSp*9MQj&l9y=6l{gqE5qzAYGTfp#0L4i zhru?4{<*0%8{D+iIftAoQxuM`7k5)hPzpVo2|BFZ338}z%hZi9C9#9S>dyZY(&?>P z3H8P|v5UuPXVVy=SaMInHaPxW9`>hGrf?%Ih$inpB>GC#oV9{XOV+yIMX6z1tXclB z1j7o+SgOF%T&VZD2{|me0)R`mneDRS?#yoQaA8eO^I2c>N`>Cmt*J&jC@MkfFumdH zyf^^#l^)EY!Hy^18I|qgJaw$G;$Mneva^iDFNIAhy977IGKS*PlGH*TD>I7RgTY=g zLU*tiJYPzITMTbWt7P$P>#{;&KI~A_Xs$1HLCt32rCyrS;=KS3v*_M&{+E;fI8sD}c&!|bpuORde9qb5QfKdr;=bcHuAJC99=zBDm{y|kFh&#g&%pbgv z5x!A<%YwdK%<+rq;3>c`s?^#UWxc}b%BBUxFW3kB!1 zAcW(4LVfj9?;qv!RbK|90gc`;#d~X^FfM^I67e=6h0sw*>aOmFObmu~<2*$c0FoO*4p96mjaLI8!YCi>t8 zEV;E1+#?GC3bsl%wrcu80i`vqU2VyH9ojaSn;2S*n9osoZdSG2bxe)eaOkd$=U$Y2%o$m~6NzBRziyCIHIi7> z0_^$Y5BH53Grq6U7|cxyu9M<5OnZ_rai9tLsE> z7KwFrN@iDv{wKykp2O#jSoPxpWEc-neD9n|bzf0s>pLdPOc8QqyFbq56WB|Lf9+ zbz>RYI;%5+zT+?CC~no*K;v&GjZLL`m%RjXMreTblAthWVQUGlJ5kRI-?unkSG8%a zr#-=9=yLx`X4!ATmsq)nbM5MBGB^Wd6~m1tjMMV)+Qb&E0nDXCFB#!DIm>R35hoGLKQ!Z2%C^#l`*@^h`b=c{Usa00ht>+o5Dr+hTHERM z_AE2pR!|sB!K!r8*R|JZQZUy;`G-XQVPK=ult?^@8%RRvSfLqxTiqEv?apQifRFjy zo8=GRF1A(PtJXj(yeqA`iLTgi*;RypxYBLN?cpr`KN>ZYE8JD3UlnSSTM$TQPst@gEKVP@FxSs=BwBoR!? z`X<<^@3_}xa?#y(m#^pbVsCsrkv!9bD9x*k6o|f-j%Ycf>lX{{F>M^zKLl<~*b&1( z3V`II=$0m(p-jQ=rEyz;Rp8~bK5pguHhwTpz_Om&+8zUxKcp%h25UGTL^O%k<>CaL z{e*T}h8zvFxlHD(qsF~v3lIzt0_2uj0aCtlX$$MNnjU!WtxcmlvpCIgRe`qk2r+zjR>%8MZAh$0^a@3E zE_DPZ1DYF&^ax=`GQH??hVlOGmO^^I@yf~gyJLh19q8X&y-|w1K;&K>J#F9y*du_= z{(fp9{a}4H)2W@+`>7-clYb=gC_X=vxcg_W0=2PqtLzl~ZgG`a>#CwK=bBawv>*}( zH+l4(Mi-$B$z0AsX1X>wKdZr!vq|NI6&exXrPV2#G_WXTVi?+)WAc#!_H}~9#*b>P zD+`i-WAZ6-BDR7<)hE&A9W}&qisbr36}~!o^n135${!9JO17rxR@W0R`vUjyF`641 z$6J1>6#pYq*7ODbvJX8Zduqo?I&Hby#*@h0%(y^f=3tvhW)1#g={zY|*PA zAq)JMZuz5pfNtd8q41jh~9DcW`DrETcjviB)EZ>qi1aMTtiN1NMtzG@K z5#M&lG?D94!3#cF0B`nRm$gaipujG1ZsxuXA+3KFIPYLqZe|=D;$!bv7ChwV5m+zD zuP({ZpQV&Q`{Io(5(e`Hn)hn-_n$;^vRZqydApb0)Oop$DV5l-D}xunXiP%a%9vJw z&LJk$OkKf0{e+`wC&hrk6%m6cnALJ?`ZC^<&sQF~Jl9DlhOONKR`z360(<1i-_&pg z*9-J~ppt9&_w#`AI^#Th#y;zbk0K3;1gDRN(MBhUuCIb^9H*HtJp9*;npap(>S4pOodgbG@_xp^BBgVy2ZojeoQ-Q79z%ciZfqA3g&9-sdhJnXgQ;}m+;r*sd9|xf*j;Yjs zf@b@MikW>`qC>4;m$)(8BkEnxOax7y>Vo=@(mkrm?=qu_pzFX;{UX%#rwU9c;M`^M~G zI6qvGsDXGf3EKEC(>saf)|7P!Jv%oo#c&{tHW#&P9l(#|RMcFyw1CXCV%z*8iD?0z z;7fwhkw>Msal|J|d?!od>FthmI%s_}rSdAGO9TXA!-AZfU0JSq<-B&awCz7q!U1;m zZ#e%mrm*_#k=B5CMr|?i-XlVCTJwLr%!Q;or=?e-2tgy~Cp@B_+~-npuNI2`1FUg6 z>OA?o3hdr}X4kpG9|FWOxSdL^0(=2xfPfMwx=rVT@B2y1NPqV}Ym#rCOmFKD6ny|s z9ya0{78Cu_Vep$Cv{h(GfVpL!cjT&YJrar3R(Wr@WN*>ym6WK1g>wKPz4*G(wR!Sw z@?75iGW&8~mjF?5;q^>T#kSK6R^Wj!CXYOH!M*A;2nabGYBCFs-QxwIwCVLC7`}Du zTHZg?B*7={ue@Ja0Pf1Ire8XL$C7NgZG^XZB5HU{X%JQ2H8g z-k@cIAT^v%G+W=``3uqX*>S$|&X0Hfy$ugZ+Wh3gjeG*j&p?CL5~dcu6_HTx=fYt1 zt*W$459viOj&kO;aVE$`Px9>qTwMcU5Hj(nIanyuY>d_p{ulS4AfK>cLsMhH(;}ev z$3etB80>~Wh`p$Ca-DNByZR4^zTE;^Q7pRc2@SK>C7M($%B-_iavHWxD{AA%ged*x zfFQM=Z@=Vr92$dcYch>(EiI#;W69%#nLY5yN7e+&dPt`OxI@+`nP|E3orb-5 z4UIGWU2EHKed~sn2IOb3)j)UTqW!pcXRk`~!Tj)$9a;~{cSw=)qmN|)&Ei#e{_D|+ zvvKYcb5`eIYxDpENUkIxt{R?>WoNhB<@?#$scB)6fw4GtT~5pEi;+~%wt*vi@jixM zDr{%z%)0gIk4@|#E(5{fN0u?)ql31N4*u#puycHQ_o`1PyFX#0Z%DfEHCk~&QkoFz zd_zNiMrxsUon6%C)yaGy`OS9IY>r8i>@R^mI!T&SompDtrk*-m1Y(J$)%|@KYzzc% zXFk?a{!*pKj!S&EP-g} z9ytkRw9#fg`)EE1-TUf3IA=KQC#eV5v&fK@Oh;0g@m8m^g+z;%^4BQu5ZeWFgU~!_ zM&kj~!&*D!n$)dccOr9st#{nEO`wLUFtYm_%Kb$I;x4iuDC)kZGoDd;5uXJFkf$k zxyxteSa$u?ubmOoPlxM0C*BHFo|qn9KNzlbv(iR$QskI~;{rX?R(5Z%X?Yy$>KzlU z2yjNfTOB0O-&eH};5ruz4t%RSl?yoMtrrH+Sz~~4Ac}ZnG$t;;n7yM7R5PRq5CS&- zh`J9#mrmbu*f^+7^daD|?Ts~ykqpHbqK^Q>0 zedzT;G^1onYQ&*vD34A@Pp$$l6eyEiJmtdHTZBOr*`V8eA1aU)hlcI{@W7T3lcNR^2G?t)!DK{@i{=)gec=ngB zjubEwAAex=SNT}(F?n4fY}Cd|HGF0SVPA4d(?2f7b3gy^!v)HG!yQ9#dq-XlbCU`Z ze0MAe=~LSudHl-7MEJltaCjE)2?wG*n)P+TK=z-!+?dN&C&a_cM6=+U{<}7I07o1e zEqc0G)7471qo;a;&`aDAPTnx+05w%!fR+6>5kxF4lf=!3%r()j(CKT)1eLiSL z-^`j`r6xKPc ziG?(;duG+L+ymP_)_)IwFV1;B#Sfl^F!6EP!gxsIT z+O8iT{tjJ7;NEaks+ZDg*LZIm{4HN8p2k}>Qeh=}${QRw6Y7%EL&1|dcJnbbpdeA(>jW6rBI z)S&w4bCj1jObR_cC`xq`s7$tgkG)*<#Xr;&mr+1aC;HOeenGj=R@yQbW8t5BHl|1s z*9vqac>$oo4fC!@9S~eyHI(~73v^;Il!XL}ot_3Q%MT;Q-aSlfClMYDem84G343}K z*w^=GI$`NQoXV~Cpsl5xkX90gX4azTW+%38^Wrv0Cs4nl2L1-4PHV_BJpdWw%%c0uLEOyPv2cgpFG|>* zl%uf6ML?eB1% z#vV)x_7FO^$M&1{ygjS1!LcP{?$P80`A*o&6+%UcPyr`68Y8zuJfP=(eLXQP^)7JH zY#@!V3bvXB(H|+L<6ZhK8?|$r)#w? zysNMt${Sri1v?FnVBLZKx++L#qg0H=8J57R8{bm}dBLOoo|fYT6*{tPzMFm;IAZ$= z)U^qUD;(Xg8J_cV>wb3$YXJe%cBT%O&r~VE?nrs77S2pccc9n6{pvsXtYC*z>mhI8 z~7$~qjB|06V8UOWbZt#Pu!|JJ4y_72;gSkL!$w$6#ockFe-SWs`g#QpQ3 zEcc((f;tMTSODXT^;v45VsLIzwjuLWsU<+RYSub}{i&>z-5gK$4U#=_(U(kX$MT*S zn*>hA`gs6fFXJ6e5GtWV)pUrizMjy7@&D^UTD#+}g0)CFKJQ<g3;eN7ot0kTo@NUa1awb~UpJ3wvRJt3%GVGdLdXWMJJy`V@roUB+PE-t9GgI=$s@VYc#vMzdpue6S zmrMK{fz@001FNr|tzAp5*LfExVAr4P0lX9RMc$j+g;gRpXc-ETmAKKrHK|~*#Djb&o6rJ0~?JhkfRQF$|NJP^K)Et zJkAY)3lJEn_OWa6F|m_5`S&N$+?^4+D{|4NufF}4#8o}X=*0oIP#~QO3Kgp@H)z;y zCk2RpLHb{!Rsv!hg*-+z3;*~8V%suPW;`d7@g(UB2EnFJG&~5K zpPL_nDjUcK0xwt$((q8$(E=t8vbe|7|0?BHWBBIH8;(17o~`q;MJU9?#3YDlsj7y2 z;x^3b=uo~wP3^W@b%->~$jHd^X(%my0*u-gaHw^LH~%u+KHAOUvt=&=BCn@kC#(oo|By#LIrp z1=KmYE4w@gI5ELrh|;#>kn&aYeM<54(o%kfo(MIGp(V5D&z~a*WA5%Axq{;!_rpt_ zXXNH)XRq#7|8?n7)Td9GuU@^PCS(UU-FEK`wjVB42G z!B@!X_qSN!{@3Z>@B{I4g>aU6ht5mLukY%Kz8xVK9A#42U2CF@doe~2qTGzK%7C(w z)i#h-c>cUtU0pr)#hBrJJNxd@2^XHH&+wZyBaKyz6T`yg&xU%Y%iQL!lZZ#bRfXf_ zv@xQ!Mvp+2Q7ROuHS$-`H9lx#6e8HlkdI?NfBv$vvZ88lHc@I5@!ZA5buLPKDZd7H zZ^PAlXD+&}t*wVSRIF#(3n&KopsuB*g%YGAO!zhw7Z)SuJFWpaLb|q5+REr_5YF$t zi{LV<)d|-#^oWj%n)A%v!w1svXzA(2wgg>EgRarl)#bQ-JB+0>QCuIq&r9S3;<&`7 z{779r96XcXvg0cG)w@zCt-SCthrt*=D=^!+q0VUm@Pmbg1)S7CQAsHZtN`dNmp6)gSVGqL-J-wXTS~0Z1RzFI+!Xv2DQp3{HGNNC`eyGl?f@QI& zm7y1lNh9~RXO<6%OxNP+pfmneQ64NVD5xFI|LoV@f5eyG)}}Z&KhMF%rSks$`^3GR z00!h24K%vFy?6WfOqu7prTEq_Gr%rw`|%@;rOJT2${=40EevErFXSXOG&Gb`P%wx| zlZX54dq9!}*7avJ4o(qBOMGRd!jZ7QUW2daT#S>-sQUJrSjiSyprfms{p!_em6&_Y zycvdz1q1L~aY>2m1{R}b zhn###92p&*#j5nldiwkO@N{vnEo)4wEUgIQ%hK}l-1DkZFz@5!Q}6WE_D@`PgzF?K zASVSCw!ldZWED?zGE6kmbLtIEB(PN=M!_L1F1SIiz_`}s?>9F$bCrL09Ibq8V`HPJsycuw zs2`s7!kKl(@MZlRBqJj$LoBKTJGSl5(agh%gwwt%&_ro@8tJbSG;DQP%fYW`x6Q`J zMlHrcj4+)e%5mSPysWOS4DX5vY2hLRcvA}QRo#y}4vVjfuXpf;rxP>2c%(+I|i>6UX^&E$6!YjkhP*7F>t$207fjz^rFJUQ(GCll*3C+n$9VZ6RbTw zJrlidxjPjgF;8tDNuh7tV;e1D5c2qjgh>=~UBbLN{ zvd4AX;zp|y2V=v-Z=(7kNCz8;>h~0MneVW1`90HCgDC6=A)&d$z(NdbEY%N?hc{6qHdgQ%q2hPs4*Uw5eNMyAoIx&x4)a^DWr_w^AmqUc7B!Gla2$g`3vH=f@ z6?9Bg*U%8B*)bH(^3wML_W(SKjEh65#0hwgkF;#zCnnOxrA$mx7Ope;?iVdw2MVUr z^%2Z2TO$kEh1sry^59f@pSbkdvKLi@;~eXC!#8Fl)ZDgT5GbxY8Xy-lR1R?xA)8KkRjHb&~NWVU(U@MHD4-v&#mxWy8vxF=!md{Ex!mq_p1Nex6T-_O6r)c2JLM0CY zAdiMtk5r}*K+N+*>*6mW8&IF3^;YnQw%46ORA24rrnI~22aId<7UqNQLD|7K^MlnR zR@-5nI8bJyHFO9#iSl6Lufon@Z+LC3Ja%?20)Fm>!tM~-hfN_dv56i^db_!mD=I1? z782Z%Zq`AJl19MQRqx?y^u=xgpy$-eeFOv>!XTbwKT@8Zn%c-0R1D&dnU>&)bT&}~ zT4Jf-`=<$Jqi7pkaXWX!MyKuF?8WohV1vqj*~}O<&q>S&^3;C;$OS3&NV$D)x&4Tk zc$EG~OJZbXIs{r@zC5gPTMcLFj1yE-zkj#fwD~-6ur~Pdy0)J`G4I=+ zQ%@+Vs&0*vRpBw?9y8=at8Tzk+5DOPnMlva=(C*yEJ@SAAeUVuv(!tKP-NsWbyi{G zj3|z3J~PhY&q}HD#Qkb~%otD+{p*8cpYnE6o55nr_2i9=5?K}}zr9we=DbWzol{w< z128c0Y#>e&w>8>X=1Sq8U!Xc%<4Yw8WhF|B1fZSe@ZEvseeO3NG#t+AY&CXL{fygF z$Tg~!R4CvURcffdAqT3k+)6MX#eI&|xo)L1lfFJu*1J1sU+%>?GL^W_OrV!w0cAsN zsG`|fb0{#fiHh|4GCSQID6U^=G6b-Fz&s$(>&+86Ik||hmH?)} za_wB+JTWy*?dj=>efHknQI}E7qj14=oPNL3eTd)4b&i2y$U_rCm&lJFQ=l*|uMc`A z(r5%YRmjy{xqR893t#`!y4DQxwHl8fe_W_rSrR_l$ddFd|5Z~lQByHflV?OGJyseG>V7*uC z2NrbQG;XX$yv9Z@n09VwcWZS-T+}R6EomGlJcb5JZx8?F%(LwUf>3cnCWvL$UQBo= z4aIx8E4_H}BFktG_=Hjb>`-8`nBToU-Y(vrwUY$UI_c;Rl|i|$4hYY}W6OEHT!(ar zOK0yutO-LWRh{V2C@QnZEm0WcE)6Mip{PXM9s}%Fu0dI$XUqE~ARHZ1Z|@EJQ9aVp zflR`}+?=0O2v@z#4Ppsf0M1?05lSNPnBad+C;H9|#2by|$i# z2sy{N!KbagT?3eI`r9piobVl>KlB4r5}&+&%`Ww$#5vP*wNPM}HahswxB2*bOJv%- zopIv>IEr-IJ#1R2o_Nw;S!FOST(PREDsi31xE>1gX!$IIppeX>?XpUe#Mq^74;NMU zwVU3(d`N&*0H8I&-UCoAn4UI;j9ClSzdpYDt0=8m7$At4D?h~~ZNPC3P)5ndCL2Vj zV6Fp8xE&BH0mreN62S1sQ)qI$|M~XX6q~U-kE&g*S+lpVpl#o6g$e&_f}>8a2lDi@ zz+!I;3s-3bl8&`LuNY4h^DJKQ0zMgv4aj(ElYv(#wVoN+PAvO9I2QODgn%NO!;bYk zmgLuk9)aM$@52>N#A?}~EfnO?;<&~V7-<6paA#e|%cJgNb&`xNepP{7JuOJgUg8O~ zb&pndH*~jQME{lq1*Bzn?Zr+aIERQ$$Ft9W(`G(>B?*T4n%pAqCQ9_e2`i9uwS!XJ z0{Szr84G-+*xEkK+bqHGT3@Ws!EV_uVbIvuut$()G0A7wCgO@Zj_h}1qYV0db_-2U zo-?Ce(_8Yq{IKe&w{&8n_Mja@{Bmj=Te%F4OA7~|nPGDp1N8qcLAF8Qo`}ov@CqWSzI4sEkD^;=FMSKU5+^t*k z;8QHWP545h)6So{a9Zk%)##5gG1=+qECA14e<3MS3et0}UVq3h=Us=p>zAr1b@iay zyLy6_Q^{=t-O}Gx@soIivgtk)s(@*O4c{`@fS23!vO)F%LKTS#@u_jm=PSR8*l51C zhR{cBs2rKPGfu3IRCvjRw1iH8C?3QvX|uDl6#7n8p=AzZB50$H>_PO1E+R6j-y~2oAZ~AXeNiT_sI=m&P%Z%dGwgo$m1k->!Pk-l5DuJ&rpa-E)5`2Jh0p%nK!xAg>R;_lh_V=M@0%~^=xT=M6q1Jd|mt!KSpHZW2ncJ_FuX(>`VkNWk z%z%~)kV+4WCW(HwR$HHOMff;|^hXg`Sy?lB3&utUCp(3yh6h&v_}0|?&4_!0j%MGy zgKD7+y--OH2P8-=An=G6zi#RL;wdDhX39oBDGyR3Tr#f*#I`42hu1GEttef&az(G| zd4|>YbS&Hsa{QW4p784`%#FJ;|KtnI+>xxQD0NT&J);+A(kt}!D%e?ohE_k6;{;TI z{2<7?b;lXKW%F#VEebk~19*6%uAU0c*;u^qQBAsId0}*9q;5CmNF5ud0Y*CAm6Zt-)DcDZQ(OG9-!>kfT{v~e|r1&#*u35 zso&%#K~3!Rpu+xMn**`BU*Nh~Ybw6cV*@Jw<*mj9z`r}Jtug=weT?tudemWIz5yUK zh@Vn1D6NvW?2FW->SHR6G2qrle@{GR`hBHCa0dbd4wi(3q+*#$QJ5b1LYr}=11KZj zkl3WXeQ?p^)s&S?4d2&LktN=hffxGjGrkUv?e6OZ6@*`1&*=3kWwlFE6~Y z)kIoLtF72ZPn?TeXGB)uzz%Bam5aO3Chq zlI|M~pgvK)h2{NYJb;3!xfOEWdjr3#HS!toSzUKzFG3t7kqe$kJwSGJ3sBMu{0Ug_ z4gdDY`DsN)o*nPrCF>&X1q)sT{B4LGSWZBdfmNfg(*`pbw?J(nR-y}# zO8ksJ2Xmi@1O_|ZS#1~vax7fzR^BBNzETa7L-5|%)QFdZZWL=*{>}SaXC~j>cI)vk zEC4p?+C%n>Q3hBwPQp`0J1GIpg zHdG%Pb}r@T@WK7R=OeWS$^(%sP^_zk(p+9g1#y#h_VrbnyH}c*eGcM2yT*PpHi;?Q zCB`SPLsLBq#90_p9Y72?2;EZP5cwIlD~0%vXtS){PwEe_8>+fMCw zRI)=qk2#YQe$P$##s;WEoxHvtc`j(U^_<}dh;T!Yi2qv;Vgj94>MHbk4~T|Zp)Q=$ zlNueMBXPv(lQ+z+O6x8dE998E~*3d-vv9s`uGU(EB|dyyLW5} z;<;sevI>BLwgd{sz|J)xLWGjfaA@JVx~}}!We_tiCpnCXJO$JlNqFrIp9yOH+q-tn zk6a=64D}%w5Fbb?v1-B$X=3wy~sSU zYK)nOy33&Btt;zs{j^R6qwuze_%#3)n}yIYP=`7r?D$`oT|dk*T0cTUEbTD~P|||v zCZP5Wbu2w3O(C_Fp#~JWQeIAckqY}GE7WVSUTC?$_E5Lu89kH~^?Ujp zRJ9HW#;Us(@?SxLs@li-Js=8gU^_g>MdBzGE{aI(*Dlv|J`LL3(X3vLtq1&19>fodUW0R%N<)?Dd_L;E4l>(&llvz7BIf&FI} z&Y*pjpoz0uw5&+nTdMVw1Un<0dJC-Wy6PgqPR(v-x3_wcBhFIggURjV*0(dC6E8pw zVbZsER#3Q#a~lKo%&u*_-r0bttk|&a9CRGt(%ZKI+CA#fSq>;fldY3bun!Gv0@PAY z$6o|BQHrdMXGR%Neek$l33l55F~xn9I%&|58`=Nr#bFn9ColcxmHJUo61iDmh_uiHUsfV6tcD7!n;J;#-> z>Fqj};e8=*!K3PagU?dr7QKljCkFeCkb(jEx50P6`c#ScrePTxD;_;1$Imhld{ zKBL%sVo`q;Yg=2P&S!nF*bmhFp{6ZoKK0>(;Mq}MJGl-NsecvUs_vg& zA3(2!ICxJBrN%SIbx)exCcVD>-9OoJ`eq3Byg!4ru}@<}FVWar(vZtgd}My=msOF7*&tTB&yj4?K|c@#s<DW}Fw#x`}>*i4Om|cS8 zQ9%~J^S8lMjNRan1V}x1NaTJTSKNB_(b(U<@rxLjmSN>x%$19@pL$AYt^&n*-OQSk zPhPnA91<>-AJor=p4Z&M3OD8U*k4NBXuZZ;z2zm|fSQ{sn-kgBTL zsmF@%>`AOzC`xQvT+5JvH*ddJsM^J_+r8Cr^jtmeQ+&T!0X;Sd5XuI49`=A9Ke_0h zl>9D~=Ug2}-fnA5^3vLKrD_#GNa8>7zJ3fFTPec~x-s2i@y>iP%Cvm^dT9Z_o;aoJ z@!)cMQ20Gx&gFS`6x7xQoHRY?yb|x3&duAC&7Ml+b(Km71fvw=PlLh(Khz(dbR9L=9hvA@aSk!t;*1$ycg}NT_yVtvRCPh4-Ul9L z!hbFA*@5tE(%No72bd2XH4C6PO=|Q1CPH>kOyq2}JDb_Fb?&`a8TrI&v-Ini08eE? z=T?qyiDFK}z&Im*@UY2Cf;2G@%F)2EHlkbCd>gDQM&_Qw$2xnd1~z&#n@OwfWg;8* zOGgO_YE@PbCIO3Vo9(51;ce9Ryi0Pdh<5i`{_u_I+6Qh!H)e}KQ{)Ybto8-{LD7=G z+NPYq0jD2Xmkjm6*{xM+8S)CrT;f@t@l>7RT0I=rUEe*lRbd!v1pyB9y{3TBIY@E1Z$ z_yjlzHxPi?SmVp|l@jop08ulU@eVg>TQai_U}9Q+QT#a$Ie|QZra$uFzQweoPhd-dlOchW@Rs zb4i(~10%{xC|Lp=x!AhhbWFy^c>t1Fz-k3F4kYkc-S@X%j2;v=c^7#vq<^OHB2nsz zW9(ma_eFJU+Dz$rq^S_?#$2&ae%bE2 zp||V8jFs3#&3@`u((-cQd@s*3{~gxGYA$1#B5=Zp2;J~QTXJ@8f@!clQ$8JI1 z&HGQr{r5%G_8us^GJZgk8bZqXjw~M74S5%8Nmj-S43Ru*cL*M=PctsrYgYq)98d#w zx$gXt#b11JslboP74#<;B)S`=>Q*&`3>r#e2j~1+wChRjcJ0R1YA0-~349Y>RgkIq zJ?c)7^+q4wRBd-y#k)$)aFP~H?e_P1bk>jWg;{_$1c=3f=GScnN`BmY?3Pk zhyR=%`>^g)zLhk{Q*Fmc7o*HZe)Nf8f&twog_PfJh;^iIl7#~*=V zxH8Q#99h?m#yNtoUY>WAVpj0|j4`fId1vd47P`}%nsp?qI#I1n29+=t^_Pwh*0!RnKqetMPhbLs_HHZVWj?fZ~-3IS-lx61guq_ zryf%nXt6?t0*Lom@wvY?%{rh1fnM0fiHz~hYusEew|PUP!=R}#c{T*ffnyBHi>ru> zIuN%jEeXt8zDkti@+FI&+N56_GrZmw0$vqDXwxF>hrrz7osVNRgc+T>x0zRam*}uL zbgi;>;M6=k)LEroX9$7ZuNZ%$Akb+;xxJ@9zS&sAuqZ9qzYR^ylU3@kSEJ! zly+qWg{oGq`iSO95|!HA&<;zNEVscIj*t9V@bm4p^$mIv@<_>t5U&^}qi}cwPhH$R zto#8#Qq@Jq9j$b$ZMkgqz;=}kX?axx`=& z=Q(*SXi`>T7)(^+c^5Wo_^WuCnR@F+r4ARH#gT}#q>jO~>vH4xGeGU5{rpwF4?DKa z16wQMQLG!8=2Dno=&mAj$m-25?!D6HS!V>Ge0d^+T>GqX0^-Nq^TplvJ4+)K1%RWW zsbhemaUa00sx3jda`1*ib5LXsA>`UgXarfT{;3`H@TMzve2WN+!KSQ)y{gIMlbu4b zsDTk0SG%8Ds9M1y>RBx(AGo?(`vX@+^I|Uox%vLC&7;S8%G?3Ft+I==i?j#J%Sdk{ z^TB$V)}yiYq5fNq>49ioPlmydrBCqgJ%FR?abWQE_RoV{B*L=RvOvNH!7goa+#t{c z9iOLu1rl!$C5A57`rs-}66kuc&#U;IZQkVA8t(3-OYH7BnwI?*EQ)=hn?8O}s#ySj8z{PtiNP;X{U-jv}UEz$=;(zj?)M?x^lf_D7T&GkAqf76T9YMap`dn zn_^onC5w85XajERr?wqp!kCjqp`mjrO_1?JZzG*O@Dz*n4O&?6n^>s+ZpGVtQpz#f zyu60se)O%)$C`Ock_Tp0<+UR_UM(i<9*KUSl(FLbBz^XQw#{{2Tq{Lo$<++2?h8@mt5qgH~#dOCfQBePk&(&Dy~54_i8+D?5e={P#2j)C;se$geE4t z^`N1_?I3Z${GN@6V&xVMQZQ+=4!yMT`tXJMo5_-u0gqMDUASnY$WvY=5SRS4HK8D9 zf{aDf(U+H!_UY=A0^_s`026Pt)9r~?>_UI{4<<9T`vPz2t(btXeHw{3oHQhyRcPCK zUc^jA0+`$i)Dq72gMZ^Psnbluxv!y$HASum(=T7v+1>^`9}}Zbl_nMLsBGwAOp%~5 zsixe>aJBZSKkt2!M8n=sX19L5@teHDVA->K7Bp*IEObz)u<2ucNq>(>oU70`jYt{? z+*X|rj&RP^C+ow|vjHtF47E*)F^>Rtd(eEbo<8(p)G}EGfXJfiFOho{wRvLmXBA z(#-t9_skBIsff2~$f@w^l^r7@DBzBeU-tdo+B(j}TS6 z@mLh;AeQ0Iv10cWeGMk=Mk5A%=oaU6U4Z02q?QBBqy;MQG+w3jkU1bi2rQ> z@f*$wCii0aO&@(eG+Y`RO-O5YBUf1*7Je!9e5TSGWP`OtYk0jlA|HVC#!GrRDb%+A z<+U`>IqkVw8%V5YUWD+D{s5NbPAtm-7X}5*?9Oi18v+LI2TTU4SsLj5p83s{IOzqC zBi|c%#{3f=Znxc>_oO!+HW0ljPK}S@|XP4b(t?EoiB#sjiaBwaP%R z9vA7eIm@0PW`^&REggEcwQH&${x%VR!1N<}BLB~B6(l~Ym2&S#Gn+2G>NP%Sk9|af z&u+ks-r6X;!qS>ixA{HSy+q93T?No~S3^m)e-f%PDe)YgaXW!v8N+0*y8WY@up@Sn z#WC2!>}Am>z-_2T4lX&0+HK<1v#2GsA=-CeKG78spXyDnjW@FW&qZn~!e{nN8n4)` z<6a#!F^{j_g91UnN0X~yFnl}LsHrZ2oT@O}+QX@hf66i=S|Ba~_i>sFZ;;EDrbK{x)+0D~< zZCP^R0vFLI2Herl-Qx!$^ihx-uxp^n$9sz^<9&?^yplw?6d)`jsNe@@J@+IEdO9>M zs!g8w`@rGj%TbRlOLUtw?hNld9wcH9(8$Sm<=}Xgd(7m=|LK44aA%3`>FS2~=*I%v zQhq||7LCYd;7&kjB*NL1n^ms4_-2r9IB)1?XZ4ck#0$TrdbB}(isF$A%J7n$hvfb! zh%u&LQm^uCa66fNVwY+DqI47LJ*oRY+`aW%lwH&YIts5~5Ed$^pn?iWNH-XOw19Mp zC@Cc=t)i%u0@5iZIV#;IsKg94NQ+3f^uWMbd&ckk&M)U5I9%`b4l*-O?X}llYwi2K z*ZZyw-1CQ;WTsH7Hx*ZE(VFX_`N)#0YP+$+makf5^IT4af+XK3dB}z?~OL> zCV%SlRF%~ExylE!+bq4{pV_EZ#`@}W27Nvi^f^s&%MSqm6KKR%()Qqfa0PvC9eJho zomB03-@W|X#-%v2t>h0(*Rw4=5$8*Csr)gr`&x2kb_zL8I>C~s790sT$Vsqln?Dq6 zy75+v^|-@$>2+9VM_8C=tyq0>+FVk`XQb0bXR7-LHbUt4(Vjrza==<4j+I^)NL=QZ zBJ!C=@t70l;yZtx8*pf@^-Ps#QW^8N!Nna&FOw0^*{&A)Q4|m8>X(QWCUJ{@lN=Q%>)-7sP6l4#{65&{ZE%69pPx%hr$l{*+tpLz zVtKDYLyv0ZJ^k3yYQ1bTY3Iw?Ty?v>2ktNB^Y$0{%{}DD6($w_@GH11TV5T$>L|o` z6DqEDjrq7&y|8EYbif6bz>+WMuD`0ds^Yr^epch>y2N`)#vt%%CfT#Kd`=aoiGYY2KPgzfjUI7Nl|&G=Ro6?e1*2|>6EVlvCEbw0+IrPqoNj2wAv^ZU+AW;Z3) zxMoX|&%Gp(85kn0aNvb^BHA&%cNoM6HDuE%FDkuaOuqQaTWTM}&vp2JArP~d%E7{7^mmzP$Uc8ci zXRGcY2NWs@cE5`)O+TwXYvkLr=z}dH${R^Zx>f?oKJ!Ps>Dv)Z%@6YOHA%|PmJ?+g zcrC7d3)n=oTnI#Q^Rv-_qsewdl`zr9E9t;3$+DjFO>O)Qmbh&9(5=p{cu$*hWDc+v zxVFF2WWM+<12WBt(Y)6^kTD6wMY-LH`pZE0G2!a&HC5R-(#F~qlQ*y-f0IazdPK=R zyh6!~7;Yj8&76Y@uCr985XQFa(CrW}UT zErO>}Le*_zL*P`;++#aA*+|%r%=Ty(>JyBH*}odR7{=5qT+HHPA0X%Ye~VcP7bB|G z!-NCY#HFAlp#WB&&Bv=bUni7fz+IosE^^6xoD~+Tv&GudCK;ZbnGzP>R$s=li+gJ* zOw5B=<&xhR3YT>`4CzvA1Q`mzLC8SItloAh+_ZX$$rj zTt}DcL0S(tm<(G29+G1L10gSV%|Dv+t@6(ES@E&$YR4utqdQ_tuTeI%Oy`6fXNU zyfC^$H`9XV+tSG~c2|3PYZq{#F&a_#drUmO+!blO_3r#Bk;~j$+`3TASZ-u(7$@O! zrGht~WCwbbOO8JOsF}=5FL+Y2duZL)4M!XJUeR)e;TgdSDK))DcG_=;W0E zR%0*oKp^z=7g*$PS(QA=(0BXF;VVf(k$hG57jNFen8E$onHAY3b@;S{Bg-?T*CjPg zvEkvu#|6SX4fA`C!dXCz!A1HeBe5i3gOtV!!yl&q*Yls15vW*2L4_tQFn0DaPRK=&~sI;T1>|gZ)->0q6V7r8;Rr8*Y z3S;V=G_or5^nvIQo*4^LRdE`}a&Fauo}`2Aql+rcvoupP5btzO zte@zt|qSdch}SaVI8K6fMH2 zq*=3K9_oH_d<$Pj)1}MBA+Gwlu0LA^Cz#OeHP%`rwQUSxOb$b0M}6581UWV{n^%?E zST^i#Uo4Y3|2{3-DGv8U=H5HBU71?O;_4nd3)%ufUC|yJ`ra}nQx(~mD8`CGBXW3WzQP>6BXl<2XqVc2C?lwPwA4(75q`j0I8Yzl@h{zH(hI(tYS8% zlbwNTzU%D#%fpydk6)rEe_0_pfV{E8dHJ8Z3x>T`iv{zr^J%vkBK71BY|U9Z`jco+ zk})j1cZ@+5-)rVG^NjSgZD#Pzawf*yavi}VfZrKmSsy*Qsk|uRr7-9 z>f*vy${`n+f@|GMS>7A3a2X0R(=`MF^XY|Fp5o0KGX;7BjB0DRwMH|g+^nS^jFzlATy zplUTixCm!svidsyz1vy&1Y`HC1>BtJfJvd=;GEw#b|nxllNKndBOB%0o8ppqs$0a^ z<>@}^{-yZ^2i7U5HnB(6n_uq@I}`u)LqxA_pZNdv7ySg?nL_Pr6!O* zSyF}o!t2|w#ZPW?9Y<4++l|QPF15CTRMixmZZ_CH@3A;p>K<==IYd5hZl#$%!aqi$ z*4HK^n%4*0Wh4iRTn++{GaSkVH4Js6fRkuBha&21qy_qbgkO)S(T@Zd zi6ogB&P~_@<1Iz8ZR&|Lyif5OwSyHWE}Xc(Op>UnuIh6vkw{YK@hMcz=Jq{Ejrje) z7JXc>pvw4mNLxEKNZK#Pkw}+P=sKaNkvvK8i6@jB^Ge5zRV9By(jb!&-)33KOxMeO z+X+nBAnm#M{T=wT94f_JAJcU3dy{I}C1cvG#U?Kxt1gGq>+=0182Pzxf% zC8cLFq@{L|x;neALMAg7Kw7unp_*@NuT#Z?*o{n_hTxdLhF!B%Fj0PEb~wdDCa0~v z*Qec25>yl#=KiWBh(d|zFl@^Pfc6K^w~)@?M=A&FJYZX(XI{6Ul`rSZQh=ss8h zCq|M~1AI#W#p1>zd`G`LJ4oDGts5L&P4IUF=ry7#hVrrm#2^upYB8lqrfAm<{cLWN z$`#RbA%02)K#c}rg7Zy3rnO+HRRCNR8%%?V%Kd5GyFi}9G%@DeS5On3-wj|vahFk7 z;sSzhw{mQB0IA{dvF`P$dO-d$n+OCrD9>7fh{NS7?vD?f^f^{7X83n%05%+Gn>q#t z-IJ?;ti3G|XW0L}x91(=X#uVnF)jrKi`sF^T~qISjY_$SduL{9M^}=24+C-!YRx~I znx+@J7^npjImH&i#XRRQxM%86k6lIAoTStg}f4)abl76O; zrmYlW_I{u#WVLAr7QaHw&=C+v=l~@Fz%mpgCLgd1<1bn$-hEHIl#u2^mk4BX<*hA#{mRI9p}$0trE>hNON^LzQb{tALsYTV`1|VRH*pNEc z<^alv$TeW)KxaLzgwTU!uVQ<*NE;=08l!cuM2ya~_RV|;21##0!8_;SdL^x36KNnj z1N{L07@5H&Y41Kaz>_ng-VbB}`|kJhh%4w^SU=O=x7}wNEb1XyLNLVvQ7bAX1t=dT z(lm_UF8}G0V(bH*3FM?ex_~Lzpoj6aIc(U_swUaoXZmqU-pVlfvF)}0V2k`(QF2nk zP1j>G3*bv12VJZ>^dJX#Ou*v<5>}W(_{jp`!~l&r|Ld@bL*E-kgvN0QA$#%PVr22iO+Kg4`x=1iJtX79L(sYHF&|%|G;aPWsGWf+gCqy7kZf*;HHL zzD6)#PWPUzP;6~&ML<)4mI?te5BSoawo>lXu`t<7eAe$J!AIZ(%Yo7bHFHWzN|nE# zb4!`o`GsAys6Wrine)Bn)~a~&{n0pj+zx695O0y|6XTV5vq2{-DSGLm?^@j<5XzA~ zQ6jasQ`gD?UW3EK^|THITLxT5no9j{zGm=%qyJC)rq~A9DiO5?hXjDF0z5+CNY`oO z%mDlveZk;00FI}Cl-vdcR}Lj0q#_<{Q`6mrMBo5h16n&G!=%a`$YhsQqAvi>KUiwf zJWDn1bj}2Q3~=|rI6mCzuXIC5(W1i%8?lINHD))vVg;--ZD6AzC_Zi#F!z7|{zW9z zFJG<#w%f${>tTf2M;Gw?`5r*Wt3)6sBCuSGJv9Jw8K8$Cv@L$0VL2f?8ow^h z#-i(k@@??aQv8UDu^K4>D(u_SvQdZx1YxOzt-hYy0BQGHw&gf?&fBs9fuJLn)`r79 zCXWKO34zK19sYBon+L$tuR8ErcY&+>zWXkELqI?Ph_vUb`e(b9dOd?w92^Sa=1xx} zd_XYW|Ni@L#*_g#4#3^Obs^#m0Jp)Oz|YCr9oQ^?l*Zyvekr0D(DaDt*^(%ZjtRJ3 zWbDAl1WM9OuTi2PAD;&B;NEw~x9}C_=PwoO+a1T3n>GA+#SMV^t3Y-c2FJ|q+aA$U z0A9&|dt=ZDX5WQ}bL}_T0u9I;T&La;>B5g5Dx{PjAhSF$1Ew?rri5OXU+f83S~DR% zaxga|>l=NY)}k(jVR-|`1F-(856{Jmn!xUY2{z-D9Kzo3)@5QM;|N?m_7d77eRXpT zCnPeWq7I=aXn4QE>O-H;Vl()SMd~xNZ%2VZ;jrj4Yf*89*@Nx(zykr>jyGo;?#;b- zHnRZ7tz=tK)qUcvP>RR!z=L*USbY4}KC>cPi&2?_{okV=N0+;;QaI0@Ygn`bVnf8A z-GP05I}S27J)9Di#P4ONU>~i96Lpr5BrqG+r^9F;^!m_rL6y zeZlICV*U`kZe!6v+hkrrv{lW>GL^Od&oWRFt2}n$TZqoRx|R~(ogrGlQ>(77*0riA zzw!iT!}@0RKO$Bb2>tosYAn7s*F=`XS_8bRC2C1TC(4%Y1{ggeGnwZJuf7Ai=jiUM z%t8D>ac+e-q^js^Ogl5M&Q?0+<6k1VEH8uG5C*nKNud6|3m+x4?GqGKE7Lmn4LQSN%#R$Md)?# zYv#rf)S;e*nouFcPd^`n6m^|0{n0#doz{t zv3F8iYr`_Kb>1((12^!7zW#X-MgRgVQ1Y(8(@c(sxsLdJKpIpUYzlkVeHYD{>7|P4 z_l*)#*`2n_O+7YJ;q}eF`&KLZ3h>Nb@4%IyrR8BHT5=+aeb)c-)@(gHc+M8Q2QUuX zsTic#a?Gtly&b|fj>8h&^>qK4sQ7qb{Ohi7j$w}S@cSoFz39L@uBFsTbEooFV_Eip zN3kORjm2oI&|asdU2t>#p2MLEG1MQ}u+%?EuR9p=)qi`7Kvr)&3aCTM5#Zz6MoYdR z8YwvUzP>&tNz+O@U;`nNhWqr-G+3M=666GC_;5ow@_Y#$9b&4^xUiQQ$mOB1M@407 z$tN1ce98U}wO6|OpQxd=^LCN2NybKl?3N~cQxEhbKs5keKdklEK;AH&xocYMQvn|= zhNld1Sfg!;?G&K^NaJuNK-kR8&Yo(KoLic}VQ8sq#?*JwY9V#GWe+Qx#;Q(KKv%3Q zZ5*2JW`;qFpYOk>w&oC}V9aQ~WCYd3RA5Ehe0_d6*?-o)u>AKP4TcR+dFUO#hdIg) zGERAQk}9h*_q6~j%xn@?$g)3&Lw4pI2;oUw#uPjY4MkM#v#PQ9*8-dpg+4mw@&u*vfC*!SiNCDl_CJ);N7XttYlc`kd&pKl>6=5H61-Y7881W z;mu9b{t#i6HlVjmPI_-yBm;8sz^$DgSzMTimz_L-<>V{oj%hEBsB9FMq$SLX_X;jl%e3zAGQIP&h>YQ zc3vsL_OrKpdgH`J(%rMol@i7lwX(Vp*9ljm3M8hVqG-)FE|$n!ARCdjx;II{$V&sD zLD^g;UcW{R#TBIs{=RjgAXMc<|A$ae`8vNXbAmf>dFY5`98Zl$zk#P~#H^Wio{o{- zh|?3xU`X^ZY#o48f*)GuPB-5Eh1(_SItP@??LBdYo%caIhzx7o`|pD5Ka~hm3l;pF zPd4$UUo9*}4Kn1;Q|K3rheWFNuyAQ;A0C}#Qex)?bo^Kf8lTn^j$hEDtbz@@FsNmR zdgWj+m6Votav#q4j3=I;IU%9-$>9w8lK#IhSt}|h_Bi7~BJ$Gk#~8bRa+(NQ1wXXb zf%GOW8DBDIXr?JwntBk37@qltCCU(HK;$J1%mEArq7N$f6P(V+Ocd}2H8tv;Zq<$$ zpFCJez!K0G<*p&f_6?vK!Pd0uS?z=)AL09u{>ey=0lE7X=sZBGkZvXe+poD(#)dUD zE#m?Y+j5j+OnbB)L9uW14IJ#Bl+WVD6TWqM5G=onkGEY?p~0|aAhh{Skdq+G$>N9M zOIYn!)4LW3MUI5L@+QzQ!))GOorQelM;j1*dyIdAKu#to;`E^oHgb}HLB+&?SAa+g zT&C;9efO#w?Or^K?C9@czS()t>Gv>9(rM*QIaY(W&t3E2p*&!(4^f=jz)u#g}U zE^gsca9A-=D|CE++0QY*-D5LXt?@47Uu31Tja zkZd7$)#?b*2dyStgw9}ZXlBR(B~j-2-AUh+FI#0 zCAD`I{y2BP4^lwTOvr+(Kx|4#b%5J!6FdycSYBazpzZ?!7ShuJ25-{jG_psVfK-03 zC2OGCpBEJ^`~KL)1q69@2Y&%q`l93QqtTUKM?K&cBjpN;yvAh^Dsc`Tmj3(g z3`BQ$paMog=8xWk6j8ebY<(AmLoYm$7L^ikNkh-wwc&*bK0?TI{?}PER`Gio>^4A@ zhP3gxlCqN0f>b?lvw3(5zAr-hcMK;BWht+%FAWVU(D(#OI2CZkQ#UxOWPI#92@*P8 z3$;7bas~HppaRYH>#0yh0-cB-wk7Z%7YJq`Vl<2?`^3+87AQ(W(GEOZrHE!r6dT}w z$HI7NDkwY|b0*6r!FtKf#}{4-n(3}PA>?6)kOYhc$!5rIujA}xcwvZj^Gd#V0hjlz zQctaK)tDV*0zAo*x4*qO>+caH17@VQ)s!sVJ6;BHUtsE_M2xO|fna6Gi?4~SY{hPt z<|*tZ_eWmw)Qa5x#t0!^9@w5$OX5p*6QCrkofLHX_2H~P--Qb|AfJ#Sj-Sy8+O?WO zMMHn>K#?lgJT#YL`vA6tU&PHGRtJ8nLrI+@jEPl@s)d=)!ee$DeCnlSYz1FDi=Ex8 zc1UTBNN9~rA3O;#l*_dHH|-iO1%*ZNPtnlooZy+>_}j?Gp>)L9=~D1q1yvmQs8=yD zAmFrpKIiK#xzz>W3>zMI++15g%23Ugf<*fr7`9*FJa<6$1qBCDhraVl1uLsbAU>24 zZQl6ujAHzz^go>>UA+pAmU5H_ZHWU3_A4uIITRhS$2pyC;UYlPwVKAP@M0x3#;;@G zlZ*$;G?0qRJO_X^KCwOq)uHPVu)JlR4Y%>Dc4-k;j1Yn{7I=eV;<<|#TgS_&F#!Qc z)H@E6Eu`=O6BbpI{?>pblVJp^eYF%7RKIgk+eMeJwQ0;o_2K|oK_6=RaiD~@?$G-xVSh)|jcIGJ%G(bWRQW3qz zZ$+Jc$)N~FT-*Qx8vs*E^*Ph*9k%~dEG@;WwF{Wpm&3U+T>xi zSpG}MjUjcM=6G_e&tC_78GgED1g5P>-&tNkv%-%mEqCEl?P%ZL)fVYhV^pF9??<(3 z-wSqlPG8#F?xF#O02#%@DJfWx3PIXu;?XcKKum;P>5M|i{B*K7q$H@8crL}KZMqMsXGAz3v!g~yVdLT~!EL8(&ErFj61x+B(=dryP4p)!kl$11r zdKl6Qfl(^~vNVj9u=v2I$9o~w;-xz#a1}VwNO}$)C?tC6z#eBIK?cBhNR>AxPmd?< z|2q);sE?~L$hI0}=jXq?f=iD&-cTvMX2!p@Mf)TkWT${Rof{PuQ&$uuD+Sz$!{}wp6BlJPE zV@~JiI8AiVDk2F5{Q;Tjb7f3@LNEXcfxM9A+RI?m7vVt>-rYsW$$(Sv4dKc_(;3p` zYY%r=gI{y8}+DBjc0g+cW2WZ7kbDmoVO0mT{sY1 zDkY8@*94wVa2L%OZ+y`$HR51zx{$we#_#mzO53M8;vUPb8V!M*0!`zSm9sZ8Rru;0 zfd&g-Pwk@6b@Az@euIVDuRfM|pAk@vm*u#OzEg&?z0cw{_0vgOmRnhm?%lWJw^{7K zUuwIVIFXPBd%$&ylx1o|lul)_tzA;<9oP77c9K(|PQqNtMD8hqJ1YyTJz@KQ#AgUBq%ZNX3LQ4e?GMM*1lto{SqR^d@T;KAYL98RbEUA=to-FpydEe zO!PWf!|^~oao}!5A@i+?4)_viqi@d5Xez7i>$4ZmE9=Us$#0%iex{t+uho2{sCC&dTLZ~{}`kNNI&H*NmE&=S6g9ZI=#OYZ5h|7j{r zYp79UnyvlnL5bvWzJBDWdI?zNW_6gN4#Lj!B2JstSX(w`)x#TXe4Eqe1rX zH^`pe^b)5UpSi!%>}4X@l>0}Fu(ShptHk(I4C|NZ*E{O=o_tQDiC3Q}m6;tYWHn_EcD_wure02788UpOQ+3JoA*)lANrA_^)b!d=g9z4t5F=}t zZ%e?@F?By(eilL&0;Q+$t54#py-ZCny(%;yW)kLXj^TxLjYsiqG3t|J8d2kmzYB4{ z*4^Lhtn}q5o&2U{NJvs-kT~cFfK8&zLm+2@{xhaMvJf5;0DPHns zY86dqgBj+cB8D#zvAf?*4tBL=j#VTszwZL9&z))YXvn{~c=slDUxx3?orjDFUVjNv z60j;J^9R4{&aJlhn9<=!jwrZKiM=#G+kfwlSwWnn+=Pv9wZxOgk*M_2zWG$kkA{QO z7tmGU5B<9e2wc79NAPR>b^d0-e%tNTqy+*sM}wO^O$d8twmj$Rk?)nH$)65g2WT%f zzdR6A%KDbY-4Bkyc7u}Y%|Gj6kZ{dlFMiTwMx42ZPU>>Do=c#qV`#X}Em{ZH_bTJD z?8M;6isj7iz*I|EO2re?mKPD>I0RHn;3c*9e^a*}x5^)xxZtT8uh|Z6A{U%pStHoi z4Y`vdrY&|;{~AeyL3R4o$>Vl|6793Aq4c)uI+amLbNw4ghCS7dG9r~TIbBn(xdLxJ z3_3bg1e0?+9nB;%!4_mhv*A9OwleCH6JKSdjR{j|CEcG}WL7gW z%{XkN?y;ty{wUsRFkjC(uKk4zy3n+5|CW!3M$U2CECYMP?sEW4M^c8aJuJLdm#}JY z+8na(ey@B>=#0{wuW5Qm20ykpK1pmC|FA9z|G?kFo+d)_&AY2#zTKWI|1SY6z3!Fd zxA^(nNm)M3rvJ*UluRyhV0+D5Ao8&)+o=~~=dEwGa=o}Iuk!f37M0<{Hp8ot`eodD zoV_J|gy6lWCUmf+9Y0R5C>rGne}DBlde5O#v(zewUs2<^ly3-~`K*5ScHC`0|359U zzHzFfO{%82hR=#_0%P7XW9(`zajWZowGd37ft_vmA*n)D9HJMJ$iREG5(QSRa8Tjk zy!Rs6FI_=TcIlP!k6d5ovDc1Y*AC&2%XFtctUFFoZ2V0Mz**wlKr)WZ8J9P-C>;YX%G1{e@O%2~7)K zE^+xOn4TD=tCwzkGz%M#e&z0aYi>i>ZEOCo^Bq}RJ*93=;ibRD$BuPKEoaS*{W#ck z!MObT%a<=9l*Yqm29+OLAm#q&q&cubI{AR+BoZ(@aNqz^Dq0nL+pTqy*}jFHQ%0A# zWnFYS-i@~CYQy(K`*Sqv+$RV+G&=J!pJfVw=oInZw%Je@nyE_W#1l)?lvOj7_GT?t zFUMUX+rClOmkdVLV!Uz}_ zMi*JCcm7w~94+fJRZPoMXA>}+w7;PJcS2UD5Q8ljiQ`+mCDxo6~R=9v|?+j+Cx(9`Ddu;>+W7?c!M@Yr^8 z3i_z5WKgm-NEn_e6^_hU`$@~wq2+nrSq>UWM;-7lcXFu6F$5K6~Ow{bHJ zG$c1%K{)(_EU~-cLqG=p8&#|l*<~s2qCft|Y!d(&TThOst1KjZDW{$D61J!le)Bbi zIo#jpMtWRbVTYsWar*@?4?7h(68fU|Lpz1lZ*FIvfSlWkSJU7OaOH$l&MrM)U!Y?v(kLT)ScN^%x}a1JNioc zC9yv`Jy%Mr_xBWCXxpM>V$YI8$(HXAwi)T`*?Jyjg9OzGfp!|}S)JW}_I895$*Ea< zRvqkLL_!lFFM{+QrFo!p=mm0v#jr`)J+tBvt^>P1iHY;ON%#Z)vX~G0O|>+r;|pA5 zfO}>}#`xeiY0zzBri>eQmit$YV-KWxa5H<0-J9RovWB*U5=#C)BY|5Uy|5;i?YnF@ z*>6}o;ThDM;u|l&ic{?C<$uN1laj1@!$3Xx$5%I(8kQ6wxgW!G^4}D7Te*$JKB~+Ok9=o>LFH^ zG>$HgNsYz3Pj(5N^zA0z{Zx^Jqlc`!4K%WfAw@xTqkpodt=T9zrKPlMmXr1P_}`In z2LH83qOk_W)|%NLRb9qX_NRR$;H}e!#D)l!{x?=Vt4>ih8{X?@L{o*?#d71Liep!j zxX=4b|M`peoonbna;f=`rX}6e$*t9znh$3I$)XW<1f7MWSQ3phF|J)h)&v!pF>23aLVsnVs13<(RVL#C2gRx7M;-Ud1GsJJK?e26H}I z>55xkH&!g@BE0Hmn^;X{3atjjx`!%7wtmeKti%ucq;UM%eRs4u;T(Xmks9H`!h){{ z(vgy5q(qg(H~^4rxK%eQ#x2)v^G~!t+JbcG2z}D?&ez%Dc1!aIi6eAZyp9(dFBKdu zFcDIn8j#4D%TU3Pg_aItpXJ?A4l3V0)-vz9Ccx2y!@KrjCo_ZNRFT5q zYL&I2tDGJ3JD-kG?9NnDQv7nH;yPiL`}(cZ30n(quQudpzU1PR%*^@E%(ma?+=lCR zvYVBIiQDxQzZu)b+Gm1@o9HPYXHEp7B*_PVHs-Pbjwu!pq!4t>^;iq5j8Hv8ooX~rZbOrjs86LP>IA&2ii>xhT-oJjOc zG%nG(CrVI>aQ8ROM$YNaMXKUIm8YanZXfhc@~fD=R%PGJ&MD{{FlzcL^%Pa8RQ;Kjai6H5 zEqhLyrnD(GOLD43N?g=HrI6*op&g;C`c<)-Mb?H+W$%%JTt58oK%HwZnUa!>vo#oY zt=^3vEvymK>M}i^LqkYd{<{HOs!s2^Q3I^y%nBFjchDm=7kW+%m$8J|l6qT2?3**P z+^m=^IgSzt`H~Xxnl6i(FW+;_`>?_(@JGtqkP-dzs7pN7zHw=v6Rf@kMo}5XMLkbA zPZa2BYv~q%`An{#u&0WTy%sq%)v|PT>X`7Og0m)~GHYGOkVF383r*rV1tu7`JUQ@W zfPv}eGw1z=Zr-m4*1zP!biBG^!4sag?j>9$i?v&HQxZ_T7TG|Js}z)O^-*X}NhBryGV;he$2_Ud zb;mlr@aSh3U-WgefBFBpU035=al#)Db|mK7E!kAX#q8^d=CC>squ7+xcd7e8li@v+ z*C$hw@*TThdsTywh?_#nYo^(_{hKr0==|5A)CaGrIAfU~`5y_ttYh4MM=8m!r3@Rc z5|mO(&Hm5JHDcPZjLv`GMf!~ka-GV3q>yqN``yNwNU%v0-;2PNv>Z() zC>+OIHSIskQzK%yciR{QT_Q3n6@qnNl^45vXZkIC{#ZF~bWys;@0(l^x;~g*tv~8m z+q<*nS8V&^1|7t5mmMWLfAzAb$e0VrkJtGfMH@PB?{$=2w^WVLW9Ed%ocq1XPK!l6 zr7e;Vo75*wYXk|6Hl63Glt^os`OZt!4cQXHjk?gmtn&JURn*a*6Ct`5UvxBlxa;bF z4b$h~fNXsrxPlIxVkE@lNyvH`|B%_GLvCiPTD=S_^9BXFLy>g8wS(~R;!EF-cugyOMrG%U!uUyk|KmCVcgKZ9G=e zLYA;<{sQZF|1)FUnOJ%B@TvDu{98b|gHOgTqetABd1~Q^8`^UOZER9U{+(A`oOvs~ zGJaJK){oYALpw)p;b$#c&peEOV$1-lhOIeH zbhfHlw4^SE;eU6!O1aacmYdgtTh!?Xx`nhncL}@rGh%mWe)JuHQ~b}R1*G|j3$7h0 zWXMjnbV`($J;@5BV>k`wUuEKEX&|lI$vYyIA-s=Ot}iySJo$F~;{~*$upOlo5Bd9E z+q5E4y0nuW#xh<3ZMf&4(}NDN4c(;SC18l+9;k(V?OR?!$3^sB>c1%d(h!U?UFj1A zmcr}%Y#rhfQ_UYesw+S#8$RXVF7F-~+h|i3W-tW&9@||;&6Vr-{&gd>rqtTx@J9td zRmn+)jBca5J$m|>J1bnnmy=>L5{qAN7K!USz?P*tsk_FQ{7+bUC&0Dr}*8&bL8@6>WP?efvM>~_;|H5N?Ei; zO_vxuE^KK&yp>)tf=u?|F}-Pc!90wBCGKli;ON8EvytENKV^c5PAnkJfDDjsJJ@NxK9p$>R3RFq!(E=-5{p@7DOI zoW5?>Nz9O15X$wiVRDgJ3}3*I;{VOSRLT1A;&H_z!sCxUE|&?%oO@&QM*37)RV&tl zuZlxy^l5Za=yCd>WJt)6s4iqP3am14fB;>}EC>t{kJI#;d9>?}=0S}bJIam!!zc*AN)(N+sPmMzU9NBFw-2PUeD5v)^I=6Q0j9S3N^;(z%baT%ljRW zJO983G=50lIfNfm1G?B|)fe?MGBAi^AH2*AgdG4-z|%YG`^~Q)bA8>8ymuazoLmU_ zU?y`lML2p<_g%DGAA5?t=fU=goRwpiH1hPY4y((5|K4+y8x975aXLc*&JMudQN1%O zTSbtWA`~&q1AyG?!KP(QFW?lEBLMRUkTvtA9OTl79F*z4BPK466To@^G!rrNhSa-y z&IZvU09^%a2qA<>Hm-R8wF`Qn@F;n$4F$pG=NX{9=Wz0K0xAIZy6y7ON^At!WIfEn!X49?slr=v6&@2I+<(&o_DJnuYZ4NA+x>??Q29JaNTdDamKFk( z>V$87p_N|$6KOv=ZCgD+_#F%&LoX`+?Dp;n?-TSvpqS3C1Yl9!U;bpu4#i&i>p>|R zffAX_A7;KLK`fJrFQ9r3hZ10rXPl7U{JpAvfch-dT9z0>Lzx@K#?!v`NJZc9 z$yLzw20*w>Xjg)vkMO-e&>q|>#h37V8PLIi9roIO*E<96$4h!RU{`m;C43P57p%O5 z1}jj6oSR022%kn69H!vR<_&2iwP3rT0o}pMR>tCd1);OmTqyvUnm6u>7$uNE8N7RJ z!Am=sFYLHD@HwtsvtICm?R*5mA!X<1s{)o6p**0;)Y-ael<>;o^u1)!gu$$hLZ1id zI~EO2Z@_QEUTKn_e?IVN^4D1-6+mS=$%3gutr;G<{<}}TPc8@xcV<_53ntgu+1SHS zL}X~DE0lQp0^AeeD>g1I08|o3_;sLAyf-ZH%RwH6+|>|X`J2dm44lkHJ^^cnU0PZa zx%4oo*%Dbhz^q`ixFemE4^2eKP3C}Fpce7RNvx-u52`ZFM8Sw9z>X7zOdV|(PzE=w9&BI9t5{p}oU8NxbRdVb??ndm{<#(*V&C(JWGF8$A5`$I zk{K&nvJ?meH1LLin?8l`k0w<-!-g(m#|PXzdyHt%B#;}VtU@>6K;xktxVARYQ%c@w zrT~5b>g#Cr=hiFiKoA5V35gE+v`e~t5v+%41P0BX-9AC*35)`S5dcwd)NKSTccs?U z)O0qfI}%U{03AjP3v|$f{cw4n{u6LnuA@UitSbc6mI%O@b3Ib1Q;vs%>XbbYHeLf| zW=^Dkw;Nm?X6=aH5PIE*;Lkuq0Ptx=yRar~$k(p@-it8F0G{mJTwiuU+z`hnMqFV?*0UErx%Sa?a4X_XK{N@i)>lgE?^3mRm>})&WS3u#l ziwy84FPg;Y?=$XIp}ePG)HiP{M-;n!oq(p07!z=)5gC3fdCYPzeoO56SU+-a*>gov zqjaLh+c)PUYwymqz&cjUsyjcEtp7Of@{mLzrQ~%vf^P@qW8MefGvd)hp@cfP`-^stA|4~uAANk)$DY*^#_YWA#JSYES*Z-eRQR$SQ zdx_QGAX~cxfZ}N7#L%8$N+(mlA8OV#7Id;`jCYIX>S&Lx)Sd*HyXBa#w(0~nc|%o& z7~}#mwC3bzBPW>bG#aOuXlrftTU9N|NaK~*auc_D|C%qiIf~waE=m4eKqbAEp`G=O z;J2fLg~!j^?duOjeg@M|E|CQI6=V;o+9kgo%{h?G%W|+_Gi4tk6}p+CkH~eA#}LoA zERtx0W2v$eUU!hB96Z&C@)kDnjl+$Bl<-_v$AZC6aRiD&GNzx5#0c>Fc(A4VU6shq z4R(rZuPdb;sd@8Lr!3)rC-Ej9i81=&sYIJlisUfPsoPEj_E_Br7`5+?!LiVE&tb*V-?eDQ&3cttr%BPK;D_c3(u8}R2EhEt4{|*EC z#sMkwLOY2EWXTKe>;LgF&J)i}zMF@JCN)M~ zTdN=a4!0B&r1IBE{`+3q^T#Zp`(dOnucF!v$v*H)LuzJcpltH%$-W0ycuh7MAK6+9 zRYv@}em~<<*9GY}ud5C$pgw$zdta;QWZROVeB5GI}d1*x3}Q|6=poI!~skYkb?@eKONyYG2L**dzH7 zV;Fx^M%C4r&Y`p8zuF`{MKCki#pC?EYy5%HEuoEE!-8((!}D*m(ljMpUthXHb8PS- z*=~QakR1edk_Pt_Rb|~Qm;eZ1X3__@Qk7k0IY78OXq0DHdxQn=f{M17`4n2p>@oD7 zi~JBMq-T0G(`}V~@`2Hl^KSa8K|4ZwX9#J-Zat+{AY#|`ea1n&aV+7jZwPkYb>a}ESu}-som?zk%`|M1+-Tw9Py?i6EmHfn;3w%F!PhI?7aJC>(@Vds<1%qQ2zkTSfH)sCmu?j|d z`HR<%^fRY3kR97EN-co;m2^tis#l1jRl`(-Ce@>}i8jp#3940MSzQ*(okUcP!UWV( z{8FlOZmFiQ+pKBmew&x|8CN$llRfit^vvdd$d9dMw_G_#Yl}Y4c8I*)!Dj6<>?PAgDJNC&@`FF7Gu+a`xy?Uof7X_ju0BG? z!0Zg8JQs^b?`$vW`Zq09A%s}lQwU{U#} zw?@Nei>O;N7)CB*Fp5#U3v63M9(1kuvo1uxtSOGX9KaR`aPrh=&oDDH7u(}FXA0lw-N;bV3klVnd}|%2 zsy5Z)xuq8YHo2llux+Tbb^CKWy+yUuy65XVndbZj#W$ch7hRO4NjRGPkz8uJei@a* z15)QZhX$~Uk8mj#TlzSPedy<3Kq$@6NxAkn)J*0cPFxFiCD_yk2`NwRUWJN8P-O{V`y4NXVPu~)aVQw@yo{^ z0?kG-zX*o9sClkq$tz?oY0l_ch{p2d3&aY_@rA_rC#3^P(xPo_#1?OK;gu<9_-^s>;HvpjS{Of?nl%VW|4 z!4K>sXo|HbqmW{z^$PR|_!K6~RKw~UJy&K-k)ec_0(V!iIuY;pIFtki9@e1+= zs?Up;YD+jVY@6`l11@0(daYJobz596PAU{ZYD%2%gazZj`0A0OYy zEP%Caurvi<_C$VCa*TeOAhLh|{>ruL*_txRvzcG7!Hjg4*?es}-0}>ZAjE(k=W{ z$>i6Ae!Hy<;r)XI46VVI{`7#z&oW(eIy$un-ykwkj+iuQ`z?E-{qT`5=#9H?Pfd_U zeA)ZjF`}p1(Zg#rS79gr0o*!K-%3MkoyD9k;Ck`))Igc!#=yGtUK?<+Tl1?HL=r(e zce}3N?7n$a%h6i|mtMOiaF!qzVV}K(8&qh#D^m7z3%}si>^J>X#zSZ_eA~PgjDa{} z>|+-zuQj)2x@O@EegQ8nO$T=<)t0)R7k>Wik1x{4G2~bkuekGAOR<7J726FlJ7$tV zmD7@ewBzCTGmj)Xt1_+y7n|F>ezNa*G#FWu0bTs|n)%Gyx6Icc1kk|mHSW++dD>jT&?Yf`}@+5AJP69 z-rSy`8?g$zbtU%{Pepn$84P($hwlRK)*w2bIyl>!e5YD9pD*^f5V zXDoXkM~jCgjP!9o5xo9j*q13G`_V$8FSo5z@1>I3_=yL}6M7|rUjb>PyEDhQUJ}&= zaH+foYik#yEpM8w4)w8#V`d@Y#%K0suQ>!j&J=p7EBiJ!WIH5$>7cNQy5k}63Mtb| zZ~%^++2bpkgyn{L9qf9sT@guHLg%Fw|0J?ph)bf^Vhc;%A#3fhP0?4iCgHb9RA#PD zRDuxi*Jrxl%yUBDM+wa6C5aFJ;1|z0!ldzOjYj=zD_9rjGFZ2kO!yVj@fkmgVlpg_ zhIcS8kA1zr9p|4=u9VH|VUD|*)~(6V6+0F@M0?8TN+G0Es9b+zn+=hKP0Q_3=mJ7D zT6u_LqQ47B;6Y+jqN-Zo5u$H3(#FEJ;PtRFtc&O!-_J|wW-zMjr*{=0eX zE}KcHxygO%PFu4d&rS&Hd!8Q^qMloP;f|qtp8nlpt-i*!*gnQ80$c{lSDTrb+{JE{ ztQtQ$9ut#-V=p|;aaW63)ren|`0%T7E*Afi%JJ>ZGF$aR{H^{n7TPc05F3hB_iU>2 zd16e3ps{j&*JWV)4F#SBL^TJcm??m%2K2$4$9le3=Vzhx01;aY-@^9|eJ=|J>LY^l z+!!Z#w-n7LEZ`~bJuO9*nct)1<2Q(BO{(-xVKw%o;mUA0S{Mk$j`)c7H{0&ww+v&dNC4;o%&n zotl|NBbAzC0UN&@;ns~tukgUSx*g!WX^0tMAy$#K=5vMypKbVhdoh0<2?bHI2-M9F_) zs_T0SX&U3pVr^o!bh6n#yo5B zITOP6E^%IuI=2S?GDq?WAaVHJ9nP>Q?s$Ua2i@A$nzl@bgdt= zkqW=JbBWT zWJm)Tk9q_#NdT46+CxHWTu!`I0@6ja4Yf+u?Hks>9YO=<)|c_k0_Z)d)_{x`Thee< zhvrBfo`h=3C9B`W{YmFbrxCj!eIAX>*~{`d${Zmx*4EdXW4)s#ubPX?o9LJgv%h{>0Be?WrdMPp5s!e;(NQ#v zLz~jasGw2N$HZO=f<)pKgTEz2RD1xH!LxXUSQ-4p*9Xc@4WRwlX7E2KK`+B~!lv!L z3a$FJZF@Qzib8E0kG3uo6BDHV@%i)by0&$OC~8`oCB?;=i0DE3C1LS367SraCnz`V zuoP@io_z`yaHBP%H#2ObVo+(RVNyxG1qIOth-+~rJVahsy=Yp@7Gj(PSurj>TEwj% z7axBDmm+%8G@4vvRK&{w50$IU*28v$4=U%ipmNJrdUzFr@oZ+`u|qEG=bUV_BQbqaRJ>Po@wAFcz+O>Noih8LPtNFMTLTek9=#FABAz-+ zw+=14VHWd(REDx(+;JM48)^}G1}f&L?4hCE%H%?biS(r*(AR*TaK0^_L1 zX8-=YYpbHF{Iq?TZ5ZvuV-Z6i##Q?gl)AcQt%p0ygP}r%ZC9SYKFlp3ztu_SD*g27 zUb)e5#Xd9DBS&uH72bzijVwBP_sSZh2us&+m%Uu$!7{?}lz0Bje(Hw;aO8uT%DTiH zu*VB>wUWsH6aAK$42`0}mU2GFTX~-q5={3p-@5$|F8ci%niS(b)Lx)fc)9FbYC}p* zA|mHA8(NZUfAnp*B;llIcQa3;vqICyr4kUUeC=7jF{?2NZ{=x7OVTj&&02R2 znsz}(Cuj;&PS9OL*_YwYbmZB8<#1z`H6uTE)J>dRA>atLAB~3k-%YLJps77VEYxIeqWapLXc2{*Xe}8qdCpIX0>FRCi&ax0l7rBat z*G{6^k@>aGC@sTeeM{M_(f&C?GvWHOR6xpOB3EJ)B#p zRIA3xLr$ukKOWasH4kAM;I%|&YKUIH{O%|vdQ_Bltlg5(;8!Oo*SuIv(&hIh2-UMT zR35K_0)8_wbo({(H5L^gF#pj-JFe6)0%JmJ6%H$}YpdVLe$3ahBb3klSOA~3wlrzn z%#+{s_8O~PJ+B2ug!x!3%wX|=wsL-Ba%u75 zU9$o=#J4}p<@2IbAITpU{mn7yaFRADHtTNp?4N&JXQj=m8*8yQV(mt0g%mmL3+t>L zT8{=H8mV7mtdjKYx}C$hrV83UWE}%LoVJabF^QX45SHFnarcjOQ%P)^64p7pX-uj1 z(oB`uv?KdoVLn9^qZ}J5VHt}0(zZX0X`*3;-5WHuVx&8L6)gCqb-AC*VmMOyNf^LW zaS|oqK_6Y6OpBq46s%C>%8lvyjZxR{ z=ccS*-`p@xQ*#{`E@Adh^CHFDG(M!WPN875q9h~qb=(=J-SSP=!e8AASJ&-9lx4k~ z&+H4$nEf~NHQBRbl~l$rvkcKVB$7nb^u9#yVDQ$&7x2_RZCCF9gzW@~S9gIQyZL0* z7K~I$xRv@>X={CgtTL%mG3_d|v(s<(SI66S9cJdbqv(koc}u{uevaP4lUr zl!Wv6Urckf!I+fR=&Eh!A~vg#pVPj7BRgVxm%bGAw8mh;7y_d@NH^`Ty_&Z{wLeV4 zvRCZ<@e?P`VEY;yXm0#5iW)jVY2sj2@Gv~Q`PrgSW5K`m3;hC|>o|T7Zq&q*cEZsu zZYEQrt*zbAk=kGZOWOu>%luB$qR#yxC_|P{jFg@0eL?-jO+i#`-}kLPJo{(zi4JZb zYx6YfGwB7Cg@kH79WWi|XHy&~V^E&wDfP_fXoY|mHOJu06QK?5ZgG|O{ub6Sr_HG4 z@pknG7A!sg!%*4P%FRDUST@>?DiiG%Art+WgZE2?`)ItAdzy05yMRWc>}FssHs`H9 ze+3n+P!cnLcW2zHz?0sR7atdQ3VWtT^7$92qwWMTA_$Uix}}4J$CR_8vS1|~FV5=e z5ho`4k{N3K)}GwqieP@(p%1I^r`=yNdDUW7)K7!FzH=urcfcu$#YVIgjqUrxRZ!CJ zT_QhzO)@twF0K+s1F1>lo9Wr&XVi3F!QTSMw|UcRTWs3BHa>Ss(BvCUx1a4$i-A?w zd8n~T3u>n+I1wtE{iQ^12103K3)PaBQ)o!{CnOCNp3(1{)X4c2QD(hcv&QI>v2m$Y z7Lm2%EyFRQmei54m(0%4X9w(mp<){ce}bY+!;*l}nM5(qh#E1SIOIn7D(zfn+pr;- zw%c9IrpD<7Ui`H=O_S{pgUOqceKqiU{m0D>MXXK~&hsa&JZ1FO9{gW**0})I#M#zY ztzh?$i+L~kKO8YpduMt(;F7_K$ee>cbfELSW;T7FnfZ08J7;IE2jIML96~(HaCd*m z7z?lZ5`Xl0>`}9ik;m1)nu`y=+tTtfP`>`z-|{@qX!*(Yr8#EyKfQHCh5c)@RIKHl zU73Z!*><&x1rddhwg>CEeXUC>x`sUAepp!JKt24jM!`o)e>AaK+`U^4=7x07MhgjS zl09&V8_geZ%;~U~0w1BvJ)*IHU@Q~NzzxN__4AvUGhm@$Z~WNU5TAoq7n2Jk;dCj{e{EynXE;=o zjg$exoQ(Zrb(ZxqNyAb(mctfkOpx1O+aPU?zyQZ|eIbW@Q@f$1wGJ&+B^*eIC4xY! zTo{G9fxQz6!?qoJ_r59`%3#=4g-yHW*TY|i;p4}~I~U6SrJTGti?`K=;E6x=XiL&x zv3oYZp(=bIWNb+}*me~-vB!Iw#vl`~QhW5-to)ioN}X&kes12tJ+2^mv#K>PKY8@9 zL)2dG#_5^16WX`6Jacz_67H)$t}K~VpyzaWmU%RZ-?Ulw-xEAs)k&5N&ARQ(ds_sJ zn#W5gb1$vnYslLw5UygJ)1Q<*Y15dNTpD*eN;|i{&E{i|y{rE4l+&c#Zs%XXjWa+AAZFE6l-?%RlQWiMHBq@*AoX2O$$*gPhZjr2BA9BF6T~s%# zoc=7C3_ZAk2<8twKJa7z*jWA&p1hVx*=AX5UW~Dn?GJBSiEHsXV|y*N;q0*buaj=I zwL=cZ1=NTh_|Q15mw2~!e#m5(u)neI7v@-1G5!vla@C69AFlG8*V#8K+qBV-UAXyv zVjH}CG33$`%ynVHOK@7CfC>-kI}12ED>HnGV=gSGTur@jH20|gtr6yHjwCy?dVv{c^CgL}99hvW z>qgaX)I6s=PA;`wIa%BPuLmDDbdrpZ`fRHvKa0NH=hDqiS#ay_Vui2LTFr5xQbK!J z`)M!Ff=TGbIaU&}LjB}@PwikAz*Wz03fOnQo-GWj_%)NRjSEe>pSSZKc|ZN>)uU-Q zDk}bt1S7T6zc5Q>2*}tkpGqtN8QT%1#O7unMe%yumdvj3)y;vM zd+@03#w~Fy-*egy36l5HTGBjp561T!>BBeGHf#u6@DwL4y{q$N!nQlNd#WdaXKTg+H$L1O?{{&lB1k7MyRtO<%A3VE z+r69mRzE7`rrN)_ zmL===qryy_kPM7!n>KI$wxEi;^Hz+5$?nb>+uVGcd6FK1tzd~*DqL_L{zY&O%ClOb zfoKU?4m_6n>U6AY0Va(S+Z&io;*ml2I|F2dpSa+_rw;!Ns;LRxjTjKQ7GRbdc#RW3 zX8*M!&yGL@O(H#jAuxEmoT1%VBVzF0+mX?Z0Ak&`7r4kDDQYE>bJ&ePML6l2MIT_I zbA-FYhg#-=$+szo(-?9u?Z532j1c|MxZ$dz?2PcVT;wX+b%7 zEV?MVYe1<=T!~|`?pnHaLEe_s>U9tA%8h?##j_F|Sv%9>G5Qr02lBnd5=Llh2FO${ zFwe1HTd}I@xze0Na22v7dsvMR8*??CGpht|e5%+*G zSo%<~uZ|2;-js)p45cpD|67?-Qr@JFto>cBZy_ZvbZ*H4wIpTh2*5ZF@h?O@+-V_B zwQ+B||DkLuTV!yQgEBLel@-6@oAtr--pT7F6#{8I&#EpL=3165*zuKGHrbmpbZwp2 z;KdCVU#9mDLGBZqoFk^O`e@Nw_!WYj7=q@4%>GyBLa7G;rJPn*e}LSJA+GPdfC}q- z*G50I;3C=5p|CNF=4|yKGCmp3(=d{S%N#6b1@(Ybj_u%|06M)@5r&zJd?Pdg?0BGg zB1q43dXzVhgL1uj_<3snzJ&)Gv zN^h>a%aoxNIyvcczeLd_eLy*OX5w_Xqh`$_dx@dg2V}dQ)n3g>S@5rF8O3|6=AjE* z_wW3>w?{H;8i2_J~L73&T8MGR^;SflD2Ko@hc(0qZxe{ybHLMUldg z5-Obgt7f%^xP#TSeXW5q3Mh@dve7^4Ew}*3FZJ<1`YPpHbPjQ-O!fTW!qrFJGv? zg^GUPS<7*m4)#s24<88~sd@I4v|W&o*nhmxckj160ioC57bsT2J~;Q<9jFd4;6iVH z203Ou25C3?;nO?SJvD%+baI8Uk)Y&ax^e_Q{D*?l0mO09E#)4@x_`sosZ&Ep%}<^@ zkuXqH{e`XsH(&}l^Zf4eqxI48; zGVFa-7G@S{Yu?sRsJdRO%<r6_m~G`+z&{v}vd?gf5B6dR-;g2qcd!JK9x)LfAMFvj=! za`2IV!0Xfi z*s>CSA6L`KsAJfZVJNM>xS*xCA&sj%A;&Cz)?71;ndAMMEj-cc*KlO#IrST>eq47$ zJ>GjKi8OcIU3S7qpEvebX_(yE#vy~GnXy1Ktn-YP(Uk$};%37YY7M!=_p?fd?$bY* ze7?y#C2@16UAS*_YRoK;X=~}5cIha4n#u34YYSa>S-a5TfaE3TP#C>0@3)6PNHn6^ z_jyV1H6JzICB}I@qA0ho6o)Oh<>*O`=wy(M5;vQjyGF88^~w2hokcc3);uo)OR8IcNpIt?lHrtACz`(*<7tk9w-_3b zpL(Z!!%d!ZxxrrXB&V-5xy9_-Q`2mTr}nirEnUDSeNE5$`IbMibV!ZuvR5%XMuf1= zUtsR}%ZZ+O6Wrbqez3J=wQiDwxX-> zBN5jRzDa5bxu@$e_gTx z(Xr%JQ{hXdbZYX%uaG|x0DI2ng|4#I)Ho2WYQH}$vH(wm!Y19c5<~Nx52oV>L%qU=gV*O|H^p0k=mSv+pM@{Qv9U4YW8y)`64(;VFYngbhQV&KJ8wEEbG5cF= zdg8%OS$%DuvuP7PIP3dAoGUL&F*{}94dMrdb7aArP7|kayQ9$+`?s8NGFoAlWp{Ac zEgOuJO97{H(ykurd71+zvzGB1$|NP?J`3BfWS_UYxA&-0V^at6g<2Y`5=ZYdE`;?C zBxpK?SBba!i9_u?eHamJV+?zZrP`A9VCNzHeY$$Zf!6ow(&4LRN;p4rH0Lpv60XT2 zvW;|<7QRd6^?&KZzPGO;@j$ky`Q3r(>eH4jE+>NQJsoqMI+eFGyN)^J@ev`DLcvfQ zH!LwL4a=nkWKxH`vBd}R`^!q7@XR%j`_eJ-3qVEBq@o7Y#a=0gJQv{te0-b>7N#LG z15s~YbjtO*=Z{4hKgH`Hw3z3{-CytzVTnfy4qWp|j_5SFI*-()1CMp&t@{`$Mo z$};71D{U)?iDhUC5+eZwQ2Ml+?L&xIm);9O<|54 zTtjw{7T7!IgbhZe+wAIrb=Uv??`J%(zQv6aqIb&?Wd8W+ZyZ;>?sdUoaBbQX%G(Gs zGB@W_`tGNmJa{CpLG%!WS?cBxzjXkFMi%3$nuoUZ%`9F8WXijg#ILWZ zG_n7?`-LFAZY`jyJzeM*3-uCGB!cqy=Ns3?tD}4*o_!YFtuha37KIcytFY?sRg_H@ zb6=4o-@ZU@jXJNv*lMr0kL5k{5#ON!0v2##W?sh85HF$o>Nb4rlo{}nH~q9k`=Bteaz2)(!ypIBvupf1Shaf9kPdqAu5Q289KNEKxj;IF_KiPlRajR*nG- zfI`fAcWoeL+VhiysBBJ;3Taodc*)P*)pI`YE;Wq@#|q`&eyv!2g|grRfFNk42tgvG zj|So_K@y;P)Xs5C5-OOwf`kxNc@?P6M)F?*I3O;!nJ3&3B9ObX{F?H#c?emh+WR>OAFlIrz9!2BuSLgCO5_BKuZ*y^4vcJHc$544YHG-X#xeibs z8gk9cJdq7E2OyURRxdeOgQa`6Wj4B^dsU@!`g2ywY|2_Nl1F^Ls17`l`MV*_`Hshl zq?n4NY}c%3|0o}g_=__A7CH5U@bDz4H(`8r4v>mvi(ytH@~}%8+B&&2;q(22g)k9g$%-AR& z2ZL^oWyqTQ9mAf<2eU za77Y0@tY#A3nF4zRB|%D&D3h@TW0y78&&$_aICuPs)wS|UAlJUY3M~oTy2d9HnmRo z%ra@Y#9Cp$z!$%d+xQ;Gc4-LTp7Bq}g2eh~UOM3Z*Xy3hA;*68aDH8$D$kZkmdckz zLiuMlu8wa)r<0&)P|ebvr#}fq+~=p4h49Uem!NZ2)KN1tgF4sFlaMR(_e?Wd8Tp-8 z-lW4&8LJtk?Imyv`MjQIW71vo-X`s|Hz&wNI-Tz5yLD9lySRC*do#%~7pw=b5*zoy zhW)Wi>b(_cYMQIL)#JxAc1D%ntFad;xG-waJSZO!nfu6Cc0J|jxdM;8=*<3)Liytt z70*Dz`=>q#=qWxr8jUx5TGs97*0sOKzXLi@fPzHJ3dknR!Ho1KqdQ}dtU;Yz4Ek+E zqOBXIaE@3vMFd~4Un+Q(*R&GDP)(*;iGJONGleL|A{g>a(v7HF=PsrF8p#bgi_Sr; z$XV5?$8%ndCTrH)G&yP~u-vn^x2<4feLAy1qo?Kjc~ODQLjQC(7P7FZf@q3e$a>iI z%$XqIMClic{z`(V7afq+%etncs2>w9?c~}jiDpWK@dOSk=$mSgu%kwuVe##i1oK6F z{26qTs7uzxCa@bV5D<}LbBsHpBn~M87!+qto*k6^c=>~?_`8&Wlg7V2_kJb2^==zY zwoTEH)SVGI9TREU+Tqe`)*n`@Ewf7xVdT2I(>|ZGMLAlFkH~uEW4iy7mDApOgETdR z>32h}Rfe{>b&E{1OILV&Qc}N-An{el+wCFl3V0UAD9Ksd$&8sVyAsfSZkwp_fH9fJ z4D-AB7M{3Kvx5fBj}wZEOit~ld9ZrP4>qn*_{f}okBU;|a|Kz4zfbg4pl;gz%*$x-%1*S^j?BspD^>ogd zCr^#RO?hd7ChQ~)lX^Cp;^q~0!p0&?^p&J2Z0cCXoLp96Qm5LF!g%;-);RM;!UcV& z7}7T zQW}3R(9G8mlb+D8}}$x;GW0qR(}jod}|=X1vw zi50FYZz^R`;4>ii{RcdptI#R++#8T_aOggK!(+%d3Xya;I#co^N06Vfh(mb+KWrkB zCvR5=aF{~|P-!~!tLMpGPDZ(!_sa+M-XF3>laR-qQ$u`w>XxiEJ4H9gHCJ8Je_8pC zujLWhQVofgjlnwcWMeuc0T|VoTVO}k`yX>UP}c#?EP+fmnS)1$9h;yQySvPUf1raB z`SNCqz9gmFXNlF)@@39}P;&@sKkiSkzxlH$x1?%AyZF`Z!E?4u3p23D^0~v=4gF{=rQa}W+Qu8~< zT67#$z(0jhJnyEHC)fVH`c;3@Aw?i39uCsi)>0P2RL3jDaR%;ZDDMDv6@I+s!~9cB z4P4V%CBFNMh5b5%QZmQV*rB4D`@9oUdH)UTF59o0u2A#yF*~)}(};}dc%@ZQL?B7OfA^-wY^SV+tVE&U_jD?&eeJ#&E5;&} zG@INNZ>Oic=Enngy`4bOG(BtJxiPmLK>nj`!fU-ey8b&5T{BOdzb)383mqv6@`fUK zTFHkkYhShRr}J-_UoIOyb3l3V&)vjY+z_1X=lK`+dF3@e+di}s z&$?r0RdfcU(z>1x8k>=Bp2R~q9$^6rFAvW&Q)7Ytc7-ZJ=r)P~hJKC;dT%mA!kMCMUDc_whcK}z!zsTcYzR| zt{^)cOPI|F@2)Zc?=G8}jYYO{&Hwf8x*sgDQv9XapHw~vpqE~ZQCmn^D2fYpzfCOt zVUNmZROz0kVTQo2ok4!CWOSd>CzwIZ@<}n2kWSyY$o%wffdX5*q&UU?$30J_vj@-5 zPODE0KfZD9{3zQB%`wKaw*8gn4^ zY7PFxN41R-xr9375)>mip^c0Y2a)P|aUq|gtt2BJ*+usH+IGXycif{8?cC4oM{kK} ztNmT}e%k_hB9}%z6Su$n4V~dAa&Z0d;=L6hW;!gaTCL9T)jyRsQtYfN+kz@MzKX(W zQ}>8X*Ip%E2**)F1PkRLtKBA+NM8U~q_B!JB5<7mMnKll_#c)z@i_kG0*+=1pRA42 zGv3!nu52`~4DhV|tko`&9nHJW;o*@jzDLXy#9ZdY#uUm0^vI!fKaXCR784jqfS387 z%|0cubAnd#&;Jki3WZ1L^9>`qNFL0;`5(?0Le5lV_bu!`LrE{ZX#bz@^U6Ih z%gP$fA{;yoAQPy}-jL95e05nVw&d4-fjm&rNGl}}pq5OHf60<*EBl$#58HH z!fGlfsjJmrj+y5Ih9#kXIZUXU)Mz3fIdkl z#7>+eJs{EgI$A>1QYK9g)>d^AOu}zKV$k?2!G)RL$*AKQN>?+dJHv`6dd`TeuSf2? zejfCPkapcU1Q@`CxYmFbfX>Rbb9FaWN%{qP_$Unf6#QmA2H!1t@Z?D% zcmd!SqTh`YX~21fOp@uzQOja@0TO>N!r8#wfh+*rKGFoZ<*flG5$@4)WiEWZH1LHe z*jk9R04gE9En(4>`7LC=(Gtp;+6#|TPZ5u%ApX3W$v(l%;f3lbtszjA299tY zkO;0v|7+kRx#GP0Y!vXNgbQ%=&RWQOYS?w2fDKG25Ce8|Pnu2}vHCZ|3q)pZ%0VEBof=JQ`D<*K{aOaSj$kl^mu8lAl=g_&KrzHsnQ5fIH^fB1KZZQYJFdK#&zT7i1oll^ zL(V@#5e>bt^vB*lQn?yoC%!18eZE* zfkOa!LL9m~;VCjEJY)vnvZB+{NnfUy=f-_Mt4Ly9<5n;b3_ll1$9l8gJpI1RV;nti zH@9ZHQ@VMv(hm><4>UETibpu0;7v-XB|OjE>>qpiQFRX*p1;ZR|BA}i&KEsDvJ&nV z!-XH6PqEoq4n^O`2kvkviNuHBfZBkP>N<|>$=_)SWa_32L`E+wyBPcYb}io^}Lua_avmE8GY5+ zUUW|sQbO-}o+4-tq{jYoJPPMzWcy z9yF+^l>=(-%ezosT53Kt(}@jD9DadVwx;mqBaJY?+eSHj6X;mIy=K^tTv_=7!AU{4 zhOD9*7yKGDZbzno+Z|rn?4nc&N!WE^J0@0@E%kVB9)mad-~m?KNJJvG{foK48pB@Z z-ARj}hflW1R04O_grEs0LT(p7kS-ipf-PCF9|h@&C}pw7RKcMzPxX!qjQ!~@^oqXz z@L^bm5xhvJgj7f!oQqvZ=@VsW>~=AgBnL1sf~o>?vTRJKJYt?n))^j4H(6kdB6_3u z4|(9_@MkRLmNEFegzsu3uoN;^+;4TgdlhDttw^w|3m;b3okt&do&lQZLxJd_h5u03 zZC}0Zq>0Ew#Ba22Znb@3~rVVbo_vcLt?ycU1s#VY2A1>~pNIEc~>tZ6R#koReH zVoYVc`v`s;sn!PNGU|D$UQ1^>mKrB}eti0QOK}zt5vup`U4b={JAtq(;r)j90l5|U zB%wG{E~S0LlL0M{t$9I&kSgn1Atu|V zN=-!BnSR9F)z#HcfVhV;p5?nZx4AUD7=0g5PBgngq1U52rvs$-LIDe6KOv(58T*~7 zsDyLCw(tz10-%my?4QI=qz#Ktvh$yGoBc-fAYH{F6IQm$YGmf)EpkaNqw-cz$0z{H zopWTLx;wP{O9BjxKEeYeO&jckOp9+-Kk~4L!AkBSmVNOW67_E?b2c(g#0iE8(Bg@G zYrA5&9Hq+^H0lwP2&&bJ{v^B5yLUJBgee$-HHJdL!x80M_aNdW2q<2aop7y`f~h6` z8(uqf;w`Dr?f&FRn>a^JrOD4uaT!KGf1a^U66+tQo!~&2EXR^ejWcJewpk20_dE~b z7fT(s0}UTq4^G%M@0S}`NyhRKWj_DM7gyXq6RDd z-Q=Lf6(_5C2)Q3jF=uiY<>1kWDnpX&7LC9=%V{x3CRW=v;Qy*^WBVhx|S7mhg>a zZo-gLIC*9IlN)tPi&pO)A2tvPgcmH_i z1!?;&WN)^tW*521i$Ut+Uh*uNtj3U zKD?k7Hw9Xss@z00cr}nt6bmtWmL4GL)p|X*q;lD&2by|d^bUl}5^|nvLFYI9z9nmA z8Ez0K>6FMqDF>pPGM4py?E2^(atH>Q#$5LV6n+mT-ur9zuZ+1V8A-gs7e2sbu|Cep z%`Fi8i636HuV3#|ROV}P6OvY0gwDS9GU@ZbXGBIh{^S!Y{Ss%A2#8 z`8^l!CE*k%n>8t8p=&impCQe6mkHZ;4oWmTf zz;(LpoM*_`{Y_hamNexB{bop&IPwsoa(KW!Dz&A3+Vy>4om#_Im)Lv(tT==y*fI!J zDr?c>uIu~p5A@p|Og`5B=3e(L9qUm(H?YA-QISNFN~ zDG5;)_09$)YJQ=izB{N(Mx(78F2=^jIx*W`b%t-zcCsH#HwX?Lu-0)}GhS}(5rucZ zOHxu3&8$eafqtv;C~-O;ilv@I*bQ+Ip$Q?20YxY}NqNCzns-E! zs4D;U+vza;>X5<8igXQ_;YkWhN8?vST6i>s)!REc?Cb&sFBEbSUw$%5GsT8wnLlvl z%^L8L;kwxePtKmf1^H1oS4y`(-kgSDm_E6S8v4u8&2LA$WQ#MzYOivy1sOLIaxZQd z^Hk5TzA+7_KS@Y%VtdXqTN^j}86Qh{J|!()DvL@kFjwGUgFg>7)1Q3;bM z&nZCPTT>jb+25}(JFBak6eu@&T-3PY{#>7H!CoC4?fgA()2N2{Ga6|Ts_1!*EdIu= z)Y!^UzP_@@q9h(dwGAfHH0c=Q+taW!eu;VFrnA!7Ii@k>{{1)rC+Ky24UQVE9d`t1 zYbHA#a*hg5KvGsfVY(n-F(xn{6VYGcNVl@cwr(I07*HUt8 zcgUQruou%%t?;Wg>mQ`Ph#Hc11=00IA%kJhXY!)p=A2uM1A{Mc=eFLp1}iFA(6)hX z{T!{)A^Tw|3|;w2H}Ds&i~=Mp)@%s5Vi8^{D)+w*Rb8ig;>7RFvwbGnZcbc&=V9Cn z+xT1n_u8;Aq1j5)$jHcV*&vb$^szHX zs7>-Ylo%PNFFOaa`-Dg+YWwSJYGF?1sbiqbw?GcU<#6fpWe^8;NlS-8PlX@OSHwMn zEK)qiSff|We${iLwx^%tx0mhrE1VK}!_=ytMU^dxzn@rZKHpR}m{#kC_&lhlWA*X! z)_T{lfMT0{8-ZG_m%IAf$wz5U9%ml5V+e9WLa0ah-w>|day1tb99Q-C#zs|5MD^g5 zJJ4PC5pH2@Qoan``elAVz>5S!|G>cdMcn5r2kv_)62J>f%mMrQTxYK#8OzUbM7hJ& z%0VMp9C$I6?NU;W>}*S>rV;;%4M}cPaGPY7Js#+#SyqlSSDt%nlfTrIBHw1bjPiZi zj0YY#bbJGQh7GOJbUj~2ILHz2WoLy7*-uEq4 z#sPf~bU}Y&Wn=pfW`^?Etd`sR?p2fi%m_In`=tsBpvuhuC~$)YN66k$rQMRKV!L*= zYXhpEocCoVpRqUS5iPkR^t83@NtFEm81#Axp-{dj+uOs}F5pkE67pfGp<08GFIz`+ zp165S|M&VIT4;S>3by`e+R`-NwF;kA5U9&<1Fg)%&o0nrzKsw0itw+67VL#K11kq` zWX}IYvc{TinBz*^@kju-WX@5SWn`V-yiFxOq>wWCex>WO`jW$s#jGyfhsBUKBovB4 zgbc02S7X+dpM7^(c)rbR`+>pjDDDwC58(+3MXVe!bX8kXo zU-WkiKdzIltaF6AKLf*~&m-X>8=BnkXhJ6?^9ZvyMJbk}t=+<#&m;a13?0eiCjXLS zT+Xe!xUBX13&93yzWSc^2iJRV#z)fMs?AvqSI*YtG~G^rMCOeYIJb*0$x|has)cwX z6NGMyPo^~1W(ziSI>l!|{>5VMmuYY;17=z_)D4l6=7oFv{{?8IdVzE`42g{ zpBAP4crX#pax`Sl*sz;*R47ZsTIT8K?0Ag-7Z7)06ce>y>js-8MbT}+p5S7j+{1b2 zAg$1t(|l}pYEeVUyhtQv8v&unYH(xN6N4W!L(}*E)^}RvkwO(1_yfMM7rrA>_ z{!yGE3PH}q1?+qzSs4mz2famUxm9C_YEcw+jsNfhj!(VCbe*NP2(IztOG$bNaNrroqw*wbU%__IQUq9j&aW;EFJ`Jbj2}T`pP3CoP zJA5ip*>FT#tla%fPt~LQ+uQ#FRdn-;%D@qRSRya8CvTNaSr!I)?RuQk-^@E=7rcrf zp2((OPFcD$?q}v}Mm7KKU}j=5Ioq0lB4kWm!?e6}=T_*=dvCJZyJ+7jj^J*N74IKU z(Ll-Fq%@~B{g6e)#?4@dRQ=(V+n2sNBUp0-;SY%GbcyVd1C1is~y%NSNrVw*VOo8IZMAf^$nslxmaBp1<-9b zq}WwA{h82*##W4gWVz|igy?^tOJ!#H{BtR8GV-zi3Ef=Yfsdfr^iA~F3L0gMM}dLd z@W{o8e*Vui_&PDT=eOH}xo=uNdKtFN+}-33IX9}*N|=>*2D`&au?~!lF?Ck0vJD0u z35D1617rR}j;?R6FUs1GI1)Ygy^9K^_JvQ(uMa~@Zw`;pYkOYxRZBrXarzK-=cakv zYQrb-mNkcHy!FLdtZ5!c?Wk_=VoyBzobBwzrO&5&?ncTW_~l@%B!kB_$Gt6E&;R1Z zk#BVjGnj&nhG!lLt})$^X3Y^;gW(=ea?sYtjw+>l==hC2?^Q)P7ymI{%3%6RRK8Xq ztHbNZt?!)K4rbIP#ugZQtAteF!mU>%)I#FDPWtt?B7d`U$-skX* z^+uV>DUB&n+VxjykHl@g^06?yQ!e~v+)%hkiVV_tE2=de(-UzmUv(Rq?9&d4JeyaRs?Of^Ui?EJ7jQ=FHMP}b z6v(X2WKp*BbV<{8njT1*XB>F7!RA`|4Wln*g-K{*ZrV|`fobhzpTPq95tA1(RUnXc zFKFH3y&7|$O4z zeE7tu9i$68Z6t5Zdl-*|6#eTuKz#>O;n`tQ zh#n7gCvljua#cn@e>B?uZ)&KcZDLtx%!STg`ih#7A>03P{QhT;sz4KrK6mO$?B26v zZg>vFJpGacfj#T1m&g4^f7(#YmMwTAUTx6=mIu?e}VGiBM+Cla;=WPZM6=C;{l z@8kP$aE1FcD_0#z*bcCJW_|YfCz<<^vlH*zdWV;cN&PivHGamo2%h23@(jxB7=1Ng zeI3NbBzW9Do8EJG8&r_A_`32@R%EEx?GoIYO)H*TWfw-ZwOTX026jF%O>#LmoVMD*b!^mZdZJb>o*vcsuKu%` zed(Hm>(^S-y4)F$mrwP*HK==jz!?G0^|DXB#d0oJ;-%Y88X89J{N>>4q@N_Tab40H zo%{d%6Ka$p#$mqmm%HTX^yqIKtYm&qS7lqycwR4%Zo30(#J1I=4U+>q{G~+Cn7$AZ z99ZOAe9U}6{7be+kUC86eg&r({gINl2J&?;HCB$o(Q`E9niX{R^KP;{TAU4Jwzt!@ z#G02H6VK@3sGYJSA!?INZHl*^oKV@bLta3my~2MuS+lyO#>vx1T-ZYXxr=5AXr7r4Cp_RR2LZf!K5>a8!o5>O?ZG-`Z0bUM^c`D}!@_>7F> zTTN#F?!$a$V~x7&gR4e=DQtR#nCC!et#0hpUKRXhgoHu_?dmvjt9A#N!S+yzGxcwx1YNaw5rVgipRBquY;;}QA@=) z%xEbezi}7AHQK0q~&DiMeT#--+Tk{SC$RQLFgKd^Z6X(>TF~Nt?t#0VP}E zJTfYya$pAb(4_|}bKE4Gj*2yy9i`y^bI?x~j`?TeS66WQthGg1zyNakAB)8DJhRLc01VgDkW{`5u5F_qSo@KfZUpsG-I;_Rtddt(IV9_arz>Jf)CYqHIYt^L%EJ# zF=Qt0Qnd{iYVEGgA37BR%=!!e0{*)z93;XZe0)lXA-qWp=3x>76}^bS$wU%e#I%m_y|gXo4Ms zoxoh(8FAmU^AW2Q8{XF!eZRdDhUa;{mjM)FaE+9PLKWVuY#MX{gO)pM^2SNJ8IpH$ z;Op0~6b8ea%2iF5PU99gMHkvO!(a z#wyUIeId6QU*T3D^j1oQ7Y21Q{FvnRaxxn2;z-UXq6vu3&p!WzZ&w>6Kl+XfH@K<7 zy}FneANEY(3%Qww<>h&;paQqB%q(l}k6?eZv|j7;c6sq;2~7)!ch?2`S7QzH zZO!b(G0$s%-BS(^bYaVk4WIP(X!9M*<_VAa#)egN6&az0c^#9r=Tat zu>T8T&s1cyYr{P2Btu%C5icCljFNyVJ1~J7;axd7=JdcV5tK|)t!51(4b?WD$46YTZ?vmSc zCHb!1i>JMB1x_p+&*hbtDl_}|JhT!NCAOs4Wsjr+rT*2x=lLG~g74Esy7Btpp=U-) zF!r7pQnDEBU)~e_h!p*FCTG~j`Z;&72YCery$S7#;@EoW)?@`{X&If&#T*%n?y$m# z!FKbRU8Ca0|Jb|bQ9jq^-o2W-_cN_i`09P0#*HJSn3sF@n0z=f(=K-ESgJ>*zeA$p zWeS2%$^8Xw&wlYc4K$WRZ#3OD1!?pmdQ@wLXzHNUqI*+4b%hr~B!yJ|HC+P=!5a5L zj^wgGgc&`Sk-L9aZN;D>J0z^f%y3|Cl1G2bLZgr^)bcT8DIm#M)ScK_u$o&ljrlHL zbBhM@=x%YSn6W*Wb&}~MKW66J2opsf^^o6W++zBDr5f5Ou!_vV<+HUjEpx!8QPaoc zey?$4vB&_a#tMk0+1uaTNY&0(ron7EGIRZ9BF)l?&Y%TCe`_hxtEDLJ5nISb)8%WK z%Sn-$hsJQX4||u+@EH%>gZYMwbS5y{+wA#5jca%S6sg}$Z@di~;%_~c*h@Kg)9yNHr1m-F=mN1{fq{oWuDN@d zJhax(CasIHZ@IJE2#vH%vIOY0Hr+vIcw!PzI-K{821&T}Z8}>UGP=&KUEWDR{G!th z67vrG9w~R#MStU>KL<8tJ@25iY1xCel;RZ$H8*%(1X1D#HD(TWY-=Y?-i@4> z-z;wI77Vq^Q>Tvabs!8H=6qjVvqdvr>Vq8@NY&^8nS!maBsAj3ceA?8zX@Sqo6$_d zyg9h@TmT-ft7~@MV_H@z8!LopX2=xKV}R7Xs76|^D{WqjaUhUKVfi>y+LA_PH+@a0XChs=`3&gEvZB#PF> zg<@pq@Z(Q*X$LTeoMT^J?0mYydu)mmv*C^A*A3N>T|jm*;x$|*(ELtL+Uwc zZ!Xu7*};4u=ObNO%YE=8MIZ`vU+Q7f)s0!cRK~&q3efiby{o#lbRxE}n=M3CNN4Wa zyNAN<@89Lfe0#c1ctg839KhJ1U`Uu-TL)}Cx>iWe_pgq?w$Sz?d0s9ac7tn`*&k;9 z^cn+^?Xmc_XY?LGi%2LgW5WlXLpI@`-<76CeduKR4D2p_^#UmbnS1_s6Ub{4$hK)FqmD)`GSP zw<|lu%gq`aY zeK)pwlijBGfj*H1br-*xV4}b}8S6GPuH5go-MaYo5nJ1#h&yNf?#Z3zD)Z-5Ih0X# zNX{ju{E-;DJSP*wFGKFCqIH-EeegVD+h|8~{3xhfooJMi#K^d*|Za;L*T?323` z>B6?UeKq+`j2v5Je3G1dV^JGEB3^jLdxj-acxHHJbu;BG`tr5CkwW$gN!jC{8}{$e z*z#IzqK;i2TL0soHRa+t8?B;G+IaE2L$e%Zhc5EkdCugSg^@qRKYeqTWY%(OdUh~3 zb8cFvAZfWdn^9m8GkG&w;O=ibnh=&`6o3V(Ai9RGkw-PY39Y&nVD;mJIfPgiQ;fK{ zxG<&!JDQ7nu`=7W)2eUvM^V}!N7ei8MKsdhRa&&OaI>FqttGB8$gF*w5y*Fa=%&ZS zE@v<>=~}Cc8l^QdGNMnJFxIFk>4vapU)6wt6BS&ck^K}r`>38~k*Z?Zd^w?C z#QQV)>x?u$D)Ndq)8bOpQUI}HAjc3%_=nf5#)?G2lGo4m@5EbApHyW&)E5;jOZWQp zA@YjL;xmht$v_tyPmIPc{4xO7(#Zkp_sW<`V_3GkR4XUQ5XFK$zhbDu8o*lcnXcQy7dpTRDo`>7r;!gPG&@H#1SkCwna-fkg~v zt6qkPHM^6$=^o_U&sr*|T00n)%-5H_8lYjW^>EVZ3p490uHh@{8Uq%-7Ri<8sxet# zvKndo%m-g7*H}AaDhWm1`4u!Z#A@SJr(lux{1@z-5~CQkf=}EkXy$>JyCX7pE@?F> zcp5846eYQRm`&ek<}*~tB>or+^0m&JcU+GX3`4b3pC)r_eIPMN@9o>% zo+^y-YPipeOBM{AVsdA?D0_b=e(4KQP~X+{kyHVGO{<`T&Qev`p~BXq=sxr%m59NC zBY;h{f-)Gc_EgQ!lhhB+t;UPYv7S;C&>u_39eVv}elLlV5az z4<cRe%YIxzdrgf(IP_ucwhUjBm#lQx6O8MP^rg`($~d)SBa ze>=MnG9|Pce&We5Hsu%9XA6=W0>xs(LVKdtIP|@xGY!5Jbp39nvYJbHIQ6V$wn=7E zZNeVkOyU$E9$2(#hTRE(C-!ACR_JW2R}b5c`4myKS@KVkOnlV4-MyES$&r?bA9jaB zo5W1!S&tDO_S_0lN$qUyQ9;+t&?gp2h(5F;t7d!+W5yxP-X`;4J~HR5vvPvE5YP1i z%!v%0db-7(GsJ$uww16iQ!Cug5CEA_pNWy0@k^|9x^Z-JcO7T&Hfa1-zVgJ=PisTE zUUcFoFPZ0N9y3ym)nx$A;uO_4;#5aMIF+f+JrjkcK9MXh!yCP+i=`ZwD+!|U(n)90 zXL95_c6xqs{^&j zbb_vwD1cS1xNj~`(BkWxJ~l`vccxaxh3fy=ZENk{`uZV*Ub2i(eUJKSQ?$q3!ptp( z*=$KSt%xX;36=QDj0$SWBjnSk%rUU*N{zskU#EXNR};Tha*mX4 zgfDpRl?W1M6ZW?+=N4LMtLSZeZVI}j^`T{AqVtQ2P>q+&QkgQ;sao(0R+Ie&GF6I; zV-0nJD~-F)$!pke8d!*hCHCc?ZSnjY$wXj`=)`kcXg7^GH6y z{rN%UyVQ54$3HygQ~bj8M#;3Dp;~TPO;C;!NPf4})xmNLyt zcAr; zTK0z0k6`rriAo^B0i)j7MPD;Ri4+_s`rNS7m2ZJPD`z@X=L;>6cGD6-kMTu+G2H6cV=>t`l=7qLw86yl@zk2QA~jkNE?nqlGgU6 zKULJQzJpr@&&<QSeIMJp_kVvsO9Q==jyRq%LDdC_4NQ~k07-t_{dQy+~!kJKEo~@u(2|7jNZ+#G~ZH0P)P}`S~EkH zwKYj*!wmX;PxSkg5b$`a#q6Pg*i`NfKr~5;4rF6-q8LwO^`_xlk{8!~+|>2;lbN(} z%U>^xPd{ts6i$&;N1m}JwoPVeZEm37(^qwSI@;oEv7y^+RKqyE;LX9}Dfx@UnT+DS z43%Ouy3ZuzigVN9?k#Jt5CcQaJc8s!(MGOo#p?I0SDh5WH+I7@cT=QNOpCNa2Xomp z*S&)~d?-O+7#ZAs(W{gf#G`EIDk#p<*j_%=^yVd3YBERECptO$uGZn)V&jL7Rp7*` zj7pP-OkMikT)=64XG445R*qzv+o0W!xe}Y=lc7d>w9s#vB`@zO9cb~;69VD>^fnRI zmC-5QP3i1oxpuzmiHT1!_LC8 zzpSx)w(403^@+yiBxsOSb{8usCpct~fq-nH?Lm>!JvX-)OfFM8mMUb67A z8Basj86V#Ks^3IK`E*KDi~I;qgMNFp?P0}6$DvoRHhuQs)Qo?#&e*0I(rIo;l&dg% z8z6?Gy-oxYaE!jy{ra)0z<9l&8!F~-;S|wpb^Fk>u>&7nH_a3G_DrHB_P&wVS8q?l zggsmsM6E)qpJzO9&!mISE>w+QvgGaCqiB^+)D|5H!F=zXM@wFZ7R&Y|X|`2t)`q@f zJytrdbCX+|Hr1k^5Zf%6p8$)8_Iz{770!j*0-)X(j zstL6_uPI~tUCqUj*+nL&8S6o-0i$POQ_AAbLPA8Q=7Qp{e`@$xhN0gBlA^7l&>=em z?_w2bgVA&smd`o@>;-O#=w7H>13mrhFzk`(XG^1B#VwrtZ?rxYwCI<5bIU2Z-){Qm zT)VJbSzPsbe`;!9i38TF9rNK-W@4^8T{{Q%#;>L``dnnj?GS=KVET`<8X2+GM@F6t z=UInI9lVgxvAZUMiMl96mRPmmAtsCC=KitzNU!-d=8ED#Bm#7wv&%qO&@nBySK9KS z^G~!}2YEJcbR9bJz@1@l7+vN|8y7Qx z5x(bUKmM9SK`~6w^MZay2%R7}EEa1w_eq`UIrO}D3McO&vxXn|CL-2tXttG~>%rO{ z^S+4sX7zk#tfaH~w0vN#{$sw`O#2ZJkFe*3R(pmQ2X!vQi6$m+4r^u!7rPb)k6wkD zwR7yJD91l}$weQaHDGgN|6EbYZlH+xuC&Et+d(J9L1VeeUEFTev$B2G+{xc|`~`lZ z4;x!O$t804E7HosxyX~mi}o> zWpK^;CbtJUmo14dFZcCAv}l99rd>#Fv6i|3W9@1ln1Col=AN*#2eH22F4|IlL)LDW zj{fTt5cje}$HH&V^gD8sWuDY>9kNvHk(ZY4nLaua3RZlI#A^9%lA@;lRL=`j%18sR zOYah0UXUm9%_#^Xj|)gbhjXIUO0>CEv|q`WcDH`JN&U24#2JG}z5D}RCH9p7Jztd< zXTMIY^s-NM+2xl)LJU zhk2KH)>^5#qDJ9#gO2Ii<9j_xg<3@UUuFEiy6eADo?If5D)a?uQc()l86XtK^z|*D zrvUTz0k!JD5~YDe$>%C@T= z?fj%kXLf%s;@wEW;OC1PV>vX)`0FaO50Wbu4>w=Cc_36!=C-n!ldfHJv;AiO-;Owp z8=5uRcR8@8jB>DqyCkxdqUq<$tIj?;nGsK$_$SU4Oju8A7&bcNN)LWe!m7`W4OyFexsJKv-A zo93_(>(LEknfp3d@6xZO8+afgd&1gOVaEcK(pZii{VLZ3OU_$?KkT|f>lHHsPpiT7 zpfNmFAwTkuZF#=FO+eSzI1go3#ogRp*O+E$eq+%Wc9maPd~nw2!gR~YL`Cwuex$|= z@IJMH&pWXLuI8KN6f(0yLai2xrq)5LO_)GP#&OoE+hRY`cyIjop&+K@^Tp~^1AzjJ z4myqYyOs|NV@4v=$kqJPILedc$l}^{{Ra&foK>n8l81X|jW+%r*h^u});)<%5%(5M z#}M6`kkjau;wQ!6;fHnbj+joqXrEt_#D)t!0zUzCR_D(?bjF) zEX|pI*0L#{viLSRzmT$YCHqp9k6v&G!+E2%n}h!rZ8k2Y+sJdhvdC?6s2odt-+t!O zTqlW*v&VBnkM<2FVQnY5J_L5pRyG3GR4uCIbsI^I5o{Got9PclEtUz#Ep4m1vNadw zyV4>>G+t33y?R7?HY9M{e2bM=g2xFeX#{1n`Zjz&YKJQEVH+NUzeBS1nC|X>_+LAP zGKjLM2$?!3pYIVe{lV`ln+fCZp5H%4#`Wvls`Xoe$f(J+Z+k=iaQ~jj{ymmMG7fL# z)dg%DW3ir_2dCs88&}8%*)C>jYqoMqv@{BvedE+KNaecbR$;6Vvg@d#w7WU#FQ^*> z!&MIqenGRa6Q`Ak#xYe4`SVc=AdAF|#dfha{P?%)e28~2DU_x>zPrh2?sSMhwx{*I zu=WVqiI<%V95=36;40y&r`fmBoASL<7 z!imvZf?|EeXu4O-#U2mRLT}+1-HeOa<>9xC3` z#&_DnVVe7irxCH6k}wo9R7Y{6122pELmMqzx~JM zcQwzRnQP?PKmHpB_VJ7@FS!2q%5Bctgg&nnx7Saa9_`w-wM_PsDrBm<(E(#p|G0pe z53)2WK^tEVVL{cPbyS%o(+m~=q%*XV%-46O%w(+YFb7dGyUZ;bYRnaJd2(JWBCMOT zPTiV>ZV1XumN?<#DN6`|(x< zrFQy<{rC{GrBZIVbVN!u8f&_HgWr$dDQ>M}n1waKlpW(oZ=x(UR*f3zdyWEt7h7<>dvQrb%@U zkd5m+%qq$Z#fDAOeusexo*zzcIIKJJl@CkQFmXwi7*oy=rwFM&I5})|MkG(j zR|lC$)5_Q6OJ>J9laU?DhK(X=FVRi!rQe6jJ8m~~>OMQVZg8+B{PS(T7ZmmfCLZQ9 zON=pXgiGgBNx+Q?=VCw4#zuN>)eTpURMdEVHKK_g8$6^B=*nBQ@D1eAtJ=A4q1zDPrrL^)5xmZ2v|0c zfrY8RVexRu+0mmGgL#B04+tw>jvSJhjlWO40A(um3t?!S^)L_5F z@Q%K_$mP_mF|MtgT3|V+TcW<9;yFin1Ltu?-M{g?$n_4q2+vM-U2r;rVz_!FVEdxG zY|qzY=h0P?%Dp^qj(u78y1%_=#utqvYWCf~PMfT5M{Q9c%my ziGMd<;3Cf@;i*2(Ia&=Z{L<(NzHp%krfJtFn@8&#)54@rTGyAcezKhJx?l)TX&ksA z*|GQLyuwAA{$)noTU4O_pcltRw9>z&*|+gBJezTy$HEG2xcgEw5JU$^p0%Zs+>5;j=& zTJ!spr`cf%B5y{-g-oJOXu$agoHPv)w@IO%CK>U6!QRyY78+ zAf(*l4s-c;qn?VnZXKfid+C$GOBRVkBpg!8e20h3*7<#-FGriu3^z(PF^axuveMGb z>A&&9aPJSy$v2z5NoW3?*rV=PlaOiq7RHz_d;@k)XH?`YD^^;rc9`OJES3{|EU1XD z1+R7BTv^+}4S}7nRM*D9I$urmg%y?R`FS!SKT>0_EnQm^d+}rl-GuJaWU+Xl9w)ck zwHw(4(toU^J7(`AT4c86lQ@T&>s-w$Wg`P9OFU6NQ;i9l9pAww8hn-HG$blvHqLcz za4n9}B&^OD?^kI0A?fO_&nD4Qc;?{CftAAi7IgA=`M-VfPT)U+j905^ zImJX@sP~E@KX@SJqNEBH-##-sR30M1UDeN@=!UycZ6yNPty~Cov)FJ2t_i{{4?a+4 zf@a>cTk*)p8DoEkSyGAEjNfPn@c?MifKD4107UH?cPqQ?7?08iHgzxkTshB@2{fDO z@9`37EBHw-=~D-%6hN<;TrKl(Ts7 zlG>S`4UQkQTb&nw*T0=Ew=2-q7qm0ZO26CAXBRWKmz9NXFr9Q=+_w9Cr@+qwPa2WT zj2Cgq&sI#HC(8Rk?s*%l}Esh&zjgZK$%BLPy< z@sMe0?WAw$vzY~1%(VZBK_K6 zpA&bm_hlzDo*2$5y(aEuxO+)GNNk(2DeOacGO5W`7pRijl1x}ViHkO4?^dxq^_??L z>%YDT#xB0*X(&)PaXH)#YcWqy8XI8<19j)2;zZMJ%tE< zw}s*JhOyDnSxz0oIqgIgB<@9Iwle$bf$~E@gAfQdfCxIxxpVv{Y{RHb_tvqE0=hU= zaUoEXlo~tOr4O~4R#u~E=&i}nXOl@4va&T?wA*l)2R_Kq72(Z|2mc37+EAW079PpR zkJnS^e_j5V$d!YsQ>6GNB2;(l9$+p&+sLJj8;dC@o~d!c^E*vHg4FvCydw}bfXGa` zwr{1-Zh4|P3E>&;yAuwnq)HL|kT##%d05;g4DyKqsW9VG4QaLQNy6pr8UwAxcF;G5 z#a`dA0?{f&^|{!0*QyTepOEH0E^c!Ix+*>Qq=ga=lWb&V^HogU4HEXP*Q(g#z5*}>kSg@z2*MjA zilD+++1Lcd0FEI5;*XHjT;Z-@0U5xj2))2==(Y?JQWCAmCg4KHS|A}FU?JxlvHSgR z-J@r|$l>IXOwD#$=L84NmdJf*`A5ZAR-oavQ(F=q)9trX57LJ<$<$M@UPE2K%eXi& zMj`a<#9^sG%6?TP@ho6+jG#y(HVr;dSMx*IV#x2V02VMLn-=(z_Yx$1eKH0Bpkm0& z%ZuoBaASwxpSdb+4oUFsILLk;Fh_xo=VMP#5yNn#qEFv{dE`_N2!kMeFo?FxYai%@ zu>{{fWzz+ijm)K`CFvPkkW&I?_hUedAqm>-Dej-})oC+H%Wv3I!dW0AUj=kjCiG70 zN8~t~0u3hNmdRU|IgsSGUavuh!RAb=-P)q)LX{MNsUbBVw?)KP0K`BT=$BF7Bi;fz*Iv`!Xe^Ma^$fp%6q2<%>ys{yT8*8V_2fVpS_p#w0*Kqq4; zy2i+SU!1(N3WGiWM*W%!!l?#qv9-e^cw8tb^7)aI7cK##!khs(J&i1KfG~lieyei_ zyeb_?BW~E5Q^@hx#-$&$8{40~$h^0AIreQj>sC|}Y`wn2$*tx0LT3J3+dq6a4KX7+ z=(LiSobzT1Haj>kRs|i)s#LE|p~DZr`n;QOv*EjS3j^xurfymni-9Z$H2^uqJ%C84 z00KFv;#vMEF@h$w&~k-t2EQmHROS;WkiXV1eL4Z~mb)254@ydwIZ#v{#M-4oDt!0N z^PHAQJ702#j!u7r66<=S3e-XnD9QLmJE$bcgSWozwmST-5g|&SJ7?Y!OgC6+94Kfv zS_m2ScLCHBf-{5a>YxK|awfnA%t;F)2anlNt_r3FlPbdmXiQN5ZYmU*EgZiWQZb0BbX`Op`F1bFvf@w3k)Q*er;v?t6@p< zrV{YItRU%M2hzO}Ow*@N_kf;J@#C&3g1mwna$vZlc}I5gWynxL$j~}=ul?0zz7uxK zTdrE(jYqgJfo+TzrpHRUrOYgyUHZtZ=ulG`&f$jQFI0&Q0t;q8eu`ybKwvy;;N{WI z5eCwjuWu9W6KLLyTY7UpXqN#%77bKrIgyzpCwj_TVqz2&#f^KOQga3ErdC>GKoATW zr+1T&ue^IpjMg#s zy7rZztOlt75S>3rC3Z<}tBHB<$(rqc@9Dg_YLH7~VDbVyR75 zVB^W@FZQBn#z_piUcjB%jbE+QlpeVF$jII$194wwq_pemz3cYKwF0P^N0)>?O@d-} z&03E<=)R3{q`eDO-x6E-a`jXg00+$h)5X0fhKSj~JN}^~UFzVVJZTan`<*p}upIDD zGJmX-Ul%Ea;kx#tDXyJxlvmg5se6>ua!q{W+qmFNg|@R7kM_`}o1OeS((VN#-pz8n zw?@@i-Y#oHXKzn5a+B`&4}e|1L?7yYFAk7Tf}X?FCGM18ur@<%aw5Q|W2o;?Wx_9m zG{M7s$*#_C-z+y4fld*Xd43!F*GoJAERhG$kyU+sd=j0$>}<43+OFAk3a8F|%AL8m zu(8RWIXx4ea^e$}#Kw~hr;k6&&4hHQPS1n?1(pc-io+b&s{jqa!f5ppmk=Br9MJVi z6NHpvSdxK}6v9OEUKjh={eV`VWljrUiXgteMO~v8venCY!UAXwfSsTNXi~ykoCvL} z!t4I>i2hYo%I~}~pu$LJxUjLa3waeoI($^0cS9lo$SQ7!LJ<)79HNzg>14GS|MUtO zb8Bv_TwDd?roZ%ST?IT*y?C`dno_d80lTb@7fp(cyqkQU44)I%Lsniu>tRd^Xrs`9dyE^{gFYhJ(&W~JY zI=;}!8@00%+o%SQFBN8Fm*A7`xi^CGuSdT;sT9{6@%{UEQ;Kz@yFdTn^)KwOcCn%M z=d+0j4A4I1RJ^^tGg`%GtW#EHI>qP}IuCon{5G+bkmAP1#>NS~Upx1pe?AZ&9!Egm zz8?9tZ^;l0KMMf=8r!?NQ>~a&!n5bvOCzEH)B%>@uWmc5oT2yfE0}Jempg-tB&3G5 z9yk2A(B@g zHmQ6PFnSgRTfV6S!p_gtHG&c)8qSHSnA`zm5|t3l0pbT;3Bmza8$triC9>`cu7;7N#VKI8M_MX zwdlk|F7UW#T~c1Y&Ytc_9{RI@oKWq%GgG2<-4iGt2zd=$Um;Q2BneavAT29EQB9gV z-gRO4=d8<2s&4~gR{`HQ>!QFe!7SpO3-8x}%3`&#G%nqU`e2uG9))zX^U}6IO70?} z0HDV4BX?KhlAd$-1H?lCSAYS9gTa6pmpz+OEksNlF%aqVrhU1}r^0-p3n17*_d0bpb( z+2rb+)(`M-hE3Hkb?N)N@4j4i{c|e$ytV_cQH`LuPGhyOVyc)^#I#b-K-B8fL7Fc2 zB)-pHT1G+qdA?7#S8JEeq^)rMrCUSAkrg`)_uFe~aypnUill#GH%z^~3j6;{<4r(V z$^#M~qU;iqvO3(}=X|ym)-@VEr9AgLX&ZCI69Q*!Pf&HnR_AEu2Lc5O++dx$mw#8d zr`=PkjUAnwh%0S8LY^H?=@k|~CWM97lDIq<62@xX?3%2gh9tITGo;&2F^PdeuC@*} zG&C?^n(>=G3)n_2#J{i%nU{eI8xfse4r7p zlaXJ;Ra~c{vTF4(h4jlRx-I;&6hF`b|8>0)mG>qm@SjdeGEf0m5!Pwo>EHMzNrAw< zZDxZ{Y^U0g8bVZ+%FJ76#4&$T4($>KzJeXO4O{*-O+#YD-}c3wyKAjBn%x)^d$RqA zy-_f7{;{{7D6!Sv?oi`ty}jjlWYDcyQC)*U>%7Tx;4mV7LH7u)3My4uNfZN=8qjT! z4Wi}20iTJrUy1S>BVJX^WnK-DM*;o`xRx5_qHNiZ;@<;u5Tq5%fz<-EHz<86urQ;5 z7uCi0_W196qJd^?uy*5vk#Fv9^H#cA0rYX_MM9zPx z447%VY?^<5r}s6*++Ze%>%A?BJ5bXe6BRRHG4O(#%L4n;`jneDKjN%;tWIA8{R&v8 zBTE3piavha_4sLGTwE^rg2+-8@p*xnWov6IC6^!A{M15g49rC?(CeV)8oO zCA`eu2R3e7ERWrKRr6D2fPfCW%Ky#AkNbNf5KgDc;{$#Ge^P?m41j#4h4%P*AV@fL%E-K!)c@G0S0H2?yJ2+%{X z&;-ptOVT!0>-rWTj9KJ>IT;S7KzJr81DsBT=y_^rNlg^3ReJCI2|o8UFW%~rgdtTW zcD7eyqhOu-fb$l>Ll*a12VKb0pSMzo$=)kpL$>k`?9(y*O@gUn$&kZ4kd}s~!rj1i zXElQ4^fBA17xS6V&Eo0Pr%ks;D}UnLpFf`5OtvK?ybYXLjf#lq`6CjH#ovN$C(6K# zaVH#Z9n6=`PMx5>Vei02NkKyo+!SH3BSqY6P%o!x{4s1K1uZs@+k<4J5JLf$^vgyp zr4)lPtV474z4}CIeUr)c$L?N&MjcuE6=Y%X=T3U8%{U}%^#1ZcqTi0}c5hmEJ${)` z&>{`zo8FIcBQz3A00wJ9%CAp7HokA4@6v8}bz@sjQbg_6tB(CatD7h!yYBpo%E+JemMtDa;C?9%DGz9`!4y<$1~p=-sc=4QBiHV57?snK9-5lEVx<9D~G_B)o`1F zaAw!}+$N*&Q`QhIBQBKLQs6qPUXv=MRtj)sg=sgb6uvD#oUJ|x`-`U-pY(6=F-RKB z+s_e*G&&m{%8di4w7x8G)`)LrH2-Fc!Tq0HFH-Yzn0+n3ODZ1D1G?Z^}n?XKQ@BGTY@^VZr3yE-VJ)nmJcoTPU`Bj3R!`U^^nQ8-QD|#*du#wU{f#D zl}Cv1{sPQ%8EGnTxK%ekM!ejmj2y)YiK%FYzUhIJ1wozZXaSjBN^_REKuS#Me`gDq z9v`*v`<>xuslWQeN8$F>hca9vA}Y!`RD$Z2gGGOotiFMpXu~Z*3uj{?bi6t%KGohP z6|zV$!>WrHl}N?%kfpu=4mXeAV%KqA|Ml9G@Lh)*!oya3>#*myhho*aB^GiWxnRq5 zMNorNc(m}^%maKabJC#GmpM&=zZsZF{ig?nv%PjDxK(heUAy5hS58oG=adn<#ZxjD zz2lf#U~xlIRL7wbH}m2v`TaduALqARgV^=n=^fA+e{HQPyE@xBStp^XvY@g@8!bVI zePzc?^hiXmyw5r2-A~C2;&2wy_39O!`18jmDy@UboA?S}&r~-y!NJ0uY|@H{zG{a} z{Vh}MNFD`QZSeHgZ`eK6#p~Lcx%O)%TEAmUt&}t^Q8x~BFaGT@6ZzH^Yj@(1uD{*n zUndvtaw#r1b9v%@>isz$^dYv7E2MUHPKiHij>R#){KkRzxB48d;q2f@^10D@DKg`AL#KvtH54mrV3e_bx|c{AzQN=SbTg z!pyQ{1j4U1`#CM@WaTR?9~&CqDrDD;uGrdnInexVu%*j3xhtc8#%s3L&R#!Hidr>{v5Dg(%+SDD^UMYX`!jOCTg*>F^f#dwWnVt&} zx{T???keA{02~YM^@}sy626Xp4|qBi`{0a4*P0eiIa^M?F?V6;tn>JccjB31?58n) zPs7~n_{GuDFRR}&rCR87#o%-ySfSXJ;CN%xEmrY!G-r~mBmQ|J zkJ)I39BO*$%V|U0{J7ghtfi~h^IsuvJ?ER%?<%^1_3+}!ibjo@uV zYJ#oH&l$33UwE~-G-a8}ga11AQ96HqbV-~-jmbT#kc-a(i&v;{`{mJ4B5Gs{ze|#y!>qw&_^d)-G&0nce`}X@e1GYtL*HUk$cwQdwd(x`spG1r!ioSY5>AjzdaRn z*{b}nX3S4qRuF~w=Jtl{9EcHc^EM%@HM7lF5eJ5KWM`hB&c_Vw(SL45eZur5O?ZngX5Dn}8Ku5GuWHM+GP&4HesQg@u z`KX5T`r+rh7d%`bHklt{Bcs(ZzKO-Vz3K6d_?_o17um#<=n6jWqLUl`rhXt-_3n2q z=H%zAYE-8(YndO{d?<<P`$*J`l=J6}kruS^D;nJ!S+45yaYl$E2w$eY<5&!W&)GS^cc_g54M zxg&zy*x}y`=0IVKHF$hyXV+{*^M|)K?Winak>otN!9+0d(bL(j6QTB{-zX)B&#JA< z2SSth+WZu;gh(pe_^v(Ff5(=0%rZveQ^6*{r&3ob=mu1*#zkd_L1uq^DkM(?khf!{ zB55z)yq@+Z=vZ$?@5DKpkHrE=G2nG+%|W2{;QK3|);gxI=ZJA?Hz zJ(l{P?i8DxH^rCU9SiNh0y`bcuHf5Dxje0{(BDP^ z1{{9yL2QNe$&)0fkcPw4_efleQ*OtYQ*h@W(Jyf=9-*Vnpe zevPy>YDUw}Gog!z5u@l!jb1i3_U{pY$Z9NxbDrTJeAbyYZIiOT-3?;hK^(O~&V zEhx-)N8Kf-Q3(RP$Qqds~rz~gpu!RoV4|sFZ%5Nihnip*!%x_@WHxR^m*0t zR@iR4teMQa=(Ib~-jx1v_n;(CJ4!OBKkkyhZHKGY0(v#{~@zpouVFi80|G zjzh?aD!ASB>w6G9#FHZY!~Bs_vB=pHA{7K)L+^`fww~Yk_J0?7w9tJFM!TtDuWG8V zW(F!y)W8VYi5-wI1>jowLq?au3ds_6u5|wF{|so0^_uQ~6@MuW($!i1?NC?HFY=CD zgTS%rMfX)i8sW9JpMP! zj!<7#U}x}^jsfO-mgY6U=FI`JgaI^`AL;u6S40xCF5#naax2R896$TY*;V0^%mTiNQ>N2|mb; zlKsM4o}4e2D=(hQYpDM&P1St!zY+TVP3`|YV|J!{38(*GduJaMMH$EOH4;su7*R05 zmn%sPkM0goI)u>VbOFzyI7ZG?6hRKfw>c4r;H;N~>)%8@dvaNTT}iuqr|Zi? z)O#jnUUHusc$l)$Sh*DH9Z_CEhJwb_SRPY^7AhN7exiU=3$ZYRtO;NeN>7xdJbj@@ zy7nB2k46T4A;<_rKYG8_i{K$}Ej!lK|n_Tb>4q^1!p3#1Hy z)NX*ZN%$xV3iP&q`gOvi_5)Y7n}4%D$BizPU*I`$QOxalRw}&)p?pPb3Pd|t`xC6J z+>7%7%_dpUIjpvRhuN5bRjcxejRZLqa+wzHz%i1|)V8^*{PLa)yAwKY-7;W2CwN9l zbhjLEDJn-EB$I-i5bYrP1Au4s6*#YqH%- zN5J{DnCAJhhpI0PE~!z^B^^)Z0fh?GEO~MGzPF`^XR$sktA`hgLgp@nI#b>IrNcH7 z72%uJbz#n`huoc4up7>!OfG+i6+?vo>?D5~=(g6aO2bQK3A5YD~+cHK8r%6)5_q-k3XANI_?86L1>^Y%u8JXI^?#!4@Df7U7sZ4wcc zub`q|o?JkLF2sDyEo`quRM(&wz3tF;xaTR4yOm-)`F^BjjF==NCfXPeD7gE3z*&3G z*yZSpDUaRb?-{E)(*D=m^OlYU&%I*?iw;XrA(-;Kq$(bg2Gz+n8)^><)!8VlzsTCR zH!DZ4S?sG0%#%A{0hS^?h+$nfL{XRpLVkK3?<1IXls~vscp(F&?Q?jRJ++}lV62f) z{$bn}VpLOK2jI)Fk{c|&&f`XA4SE9Xe;AcN6%mkwln;5YF9 ziB?t`aLp<0(ty~8UBxEk;i&vOtVaT(!A?QFbXMIr(3a|(ThK);c(5TRA@zb-#d(A$ zU|Y$sFqCOrL90P@%gxO6f^7plz)ro+a=33KriJ3I&P|#z`a_&3427Z98D0xgY2g@| zh&M<4w;Ctik3nv2Tip7Pv)h2HA|(S*z~tuG-lZ#Hzfs&k9{cTjr*yE<{ce^iBaHt|EqE3$9;@X^OhnJxjB zOn?YzxINMkEjk z_yRY+$TdJD6boI&&aRFEfmk5e_>+zFnH3^8uTzA@Jb#5L-32|=fmm literal 0 HcmV?d00001 diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_images/k8s-failed-pod.png b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_images/k8s-failed-pod.png new file mode 100644 index 0000000000000000000000000000000000000000..c1696a5fa42f8df4a71a6e77ded5a6fada61d353 GIT binary patch literal 18937 zcmbWfbzGE9`#!vgsDPk?goG$1u%wiP7<5W5EG@8fmvo4Vv^3I4!veabw2COZ(k&$= z4blz2S^3yYlNvYL>gg>aD42HFu7sme#6|^*5ee^U@b|WV zwKB<2U9&mczSEt7c$NO{S!qkUy4SOwtIvC`okih5glJzp?zrO1rI{CZ{HX(<^(kwH ziS-xdzRBa8V-IZ~_m5g}Y1rQUPJTCVcf#4Pfj^+J-Yc%{1DNg9?C z^!PBby5J~Ac!d0L&Xn}mNKdbG6Yf0n2)9W%KC!ZpN%s}CFOJ0}exs9qJHo#A#E5nCLrcIDagLm3kn) zys!^#Pc^e!8TOoM`(@|XJ~PZa)5hEGeRQ;J=QHNMTu16ci=C1Xh?LY-@zeitGo$D0 zo*da9eKtTz{@5B_IsaB0QcFIH3!!+na%NGq%eqS&-oi8V#KvmvCAU&#lF5 z`S?5Sf8P$jQZ}ZSF$q%^>V}L|aC+PXF}ueQVLp{936K4emeH68%5F zhFI9{`>HFpH=Ai=V?!SkK`YYy-#7im1*!4`H#qIPbQCH$I2fg1XLI=Y;YaD-TvvBy z6Y8SoDps>87cdOX-6PU5rC_KOG${DyjB-~ul6N>4y{cIX&(rB%r#pV^?!s#+D=S!k zv={!47*?z+q@|`78Rr`PWxal2AR#JBWNT&YCF)G$NK#w9rv4zC(%g8UrW6uIwOO!w z9TIujK}vfuCNi?1@RiN}7Qbp|I4zOz^lazW#>UkcG6hQ!O(tmV=yu2}(y(6x#^rI> z&URi23Zm1g-6>w5*$z!ZCEnfV)v4@jP2}h8>9$^!vgv$N5*P2g)G8Wa2(7`*lI~0B@ny?9l=^hbx$M^s`!PL@;%qg09HI24yX}Y@h zDb?ZR&yVlC&TD9XU!5sEL`Yy88pl3u=loqZN7zGh{@IdRl*TzFu5Sp0w_MT1RH0Ixwe9VOytS|R zbLrC4i{6{PFib?M`_Bhg)bAbdGBb&9D#(nJtbTo6!nio``AKZdaE93Tx*Ex>0`&rB zRNia_8I*is+Hu6uJvJ^d3rQm<5Jr83XLvQXSNzgQQkrkb+<~K*S(sV%;zEeYaN6f_ zp=)Y|G>&b_yRy4`?kjcivC-^M%ok6HglW??|98<<#A)q?KCwRAdcL~DfhM;E1f-H< z(Kl3(dp#NYHKrkq@`{RG6c?UR9Q>$xyROoCA?~AWIQrXx4(6ij&fRS<EaN78wsew-hBo)Qt9 zqQeHYNcyrahAEVMmX$>vc24vKdVbK1uInD}SD5}$xml`v$2eNBMuk_e_SU{wnx?y_u~Ik+h`JI9E(&ClEAQ`=P97Ku2S3XbC5 zxXsY^GA!k~m;L+dXt^_Ln_qF&s{F*$CeQuDQ3h%#2>@ZI1?@ zRE4qG57pH$aV#-=iv<=Sr=Dq244kdYfT|;=m2aa73`1jLYe6_9zH)P@vgF!(l%p?s z;Eaiaw9u4#15_TuIEFL9){opJ2F*Tm((Lf-Htp!W7;PryO7+?`G|Z(iwoF-!NF2U2 z*1*HWq{8w1{i-nwbkPgBB-&Gm)637y!&A?r32WFN866m)JY*#56_<_NP?omYT5PA( z+%qu%6Aq?qzX0Z?xL%!_R)VI+rXmLFP9u;>(u&znp1XL7YUAt89O}MJfhWsmOU376 zsKNr)eSf8uy z_SumAWgW}-2ly4B1DC|AMC~mURC@>wPgy}jZ(NSnqNLFpbz~VvZ5;gEa#S1vQVjKOBCLNfYiI5efepXk{K-( zzQoS5ZOQ9(wIge=%!Kymp6~m?;wpX;z2ln+?3IRME6Jf7fjD z^$`f*Bqp=Bw5slfd~&)?5_vE|krWo6Ff<**MHcDBruT;YaGe@FHAh`##xF`J*;+Rq&WwR*SWTed6bRp7&iWTO6Nu4D#qq&i9JSI2M&>?d*cFo7MQijx%>rUaW1@IZMFWhm~e+)dC})(aJgtr{LT#( zu+**y-P)bb1j)s2MB7Y=+4ZE~+VFe>ebcsstZMtV-Q>fTN0u9}ZTHH1PoA%Z&0&TF zV{>jX=r--H$1C#Sg=oW;)mw~# zLBk-MM(WSP3Oha{YTPV6wa~@VtMKUUtCF6krU>u-Ap^k?=$(q=tKS5UK)k*o`lS8E zHlz`6yapmdcRoo14j_m9HUMv@Z>9O5(K|ns>UiP-X8A~kg+=CUpOpXt5$#$`=7$CW zUp#-@h1fsX;cRSEfms8Lh`llvV}5+{cqUp4PFv?2M$=AyGfCn65nkiq$YlAi)7u!% zkRqa$(7_yM1P=%y|A5Bp{sI<7$kF}7#^-en>O;%>{gp-5Zi_XAf@Ax*tS@bzR!R$i zru+-5w&bM;%x>=kS(!zvberr|O1Az4)Kc^k1VT*kc9iD~0uSOhg9D+t3h4_$ zee{MvQqMym=kc_-(3W01z1v5)(6fKOtsg^n!Wr&Adx|=twvhX9EGdOR(vc_sK$Kz8 zxVGJY{XwtHc;}mw8#F$^`PU8nP)6Vy{g)tq0cY;RdBAntu0z0=4C}h};0{SYC8*%) z>JqWM<%I4*qN6oh)I2wSi9#TESQ-+OK^rx0g?hC}>N z!7pFJ#@Ba$wkGv=ck{}ATFB46rf^gV9 z`GtkeapK#JsN}Y`HYAc=RzXp5q{?B^<v^kdCVA#QJX5^WEKD3Qpa(iOLl3Y(zt6v$S(AMn*=?&Se%5m+P3$3oVq+WW=T`jwoe7QNhS1 zn%o(lHPtOGC@P9&QLfW_?}$)Q>HHi*!BqF=%^MU-_5AYZ&!6L8M5d&p(Z$Kvcuk#M zTw21Lz6f{TOpHkwUD-CMaaBY|3dkti4pLlEQjIqu<>2$&vJMnr*Qroot#+DelYPtS zU%x2Nhom-U?;Akm>t$xaSvsirO0P5^Jj#=r zJ3Qg#HF>A5{kY64Q9J`0k1b_8S`vSrEuElFbN4?pj<;_E_?H{_kyNji@tA_`0JK28f=y=7#IoQ(Hwmd(d zDDtGZ%P?wL7pdY{C3|Tx#;Mnq^KI?2o3X0f(j^yDMY|?(uA^j=kg^#^i2my?rIZ77%5vT)~$9#IW=_P)PZPi-F;7q^)oigD!I-&*P} zyibgi7t`I@nL)4T?!s{MX~lz>sbamFo=xjDwlgK^>5V9@8h)s8^*%pzra<})aj|MU`TST4cXr%jDM?AY z`}@rXm0B`aFi}!3vXG14JHRldrq;VIX%EKtmz9+@H%noRT;jvF;d3I-dz2HFO9^P` z8HhC&4str}Ns)#7NRyYL+wj41C+FDMk+Xx-Pk7}xZEi3k5Q0?8VIOw-+7?I3ruMSD zJ#P9FLVlz}-j2={B8NpkJY4-q$Tjuzr{#mF#6&7u+LV-(k-okh5+;+9yu4p-q9i}5 z=;r!HMpB}q8D6V_@W9PaZUqlt{FW@FhHe3@Srb=|ePPpsLtLSS;X^T7Lv}V3xNHB5 z)YR)1jYD<~9Q$i*Y1&6A@i7c{H6qAk>I=V6>(cq4brFc{Cka49nRl+ad3!>+yv>e^ zC?0czo=hU@bt;khU|XjK%$3w6eyo+{eVPBOjnEPED#3G;IwGagaJor=2~I4rlK>vh^2cI2gS!AHul zOuznx>#QfzSn6z zpa`K9cOXkC>?=v#XyfO6Jnjzh>$qUJr?tZ8F)vI_O+Dmho0~TL zNjwbaMwB?iIh?m3Pc7p@=%3dY2iUAMNXq65tZ;~kdCasux>|p@A%!QwV8~2r+0uLKA(j^svh2>?x>P^4pQVp2JC_e9OA<5=FeN^Bna?*s|n1TU6C*>jZ^XZ}jI zS-;FxAdTQ^VCF1H!pFrRkapbvBuBr6^VsB=j!Xc5EE-`tR__gBn2L(;E{RIXmDN}Q z2acfR2MO$TAqu1)u}PGr@P~a8GvtT66i-%LYwJkO6T7USUIP8; z55m3cHW?-u91>z|WF&e$LgF=mJEYWS1^M`Pyu{pHq6Zf?rPA{#+v5`E6JMY$pJ5au zEgo_Po?*QJVSz&YWX79$PJKhYvOtgoK8Mx-9f%=jH}#6QT(~ z^1ZDB13Bgl#E+Ymi_6Z!;vL~gVp0+*DQRYAriPr0i;I_6ZT|wlZ+s`?_k1bO;j+q zX@!J@Mn*>BCTqQR*Q% z4(1gXe0Wr@y?gfT+1{Q9h+P@Mt2{T)dtR^(N@{rskP$!^NKIFl-Hyp&5QQLFz_h)0nqgdoSviyRCu&b5x1vmHV0X8N zo#+dNMMP4h8=aAuILh-)d{*>BS>&%HU%YrRSjw?ntpCpFxeRd&0|Ff*bTN_bEr@_6 zC65TKEiFl&8+#R+yxq4Z?lT&+Zea-PEON|5KBbz{N_yo)mJ@e2g&hFFbfh(QZN6k_ zpImjLc_C1HPxN_sPGUI&lSQ*C@OKL35+AgysLFQ>H$jjW8@{LAn+zOsT9AB2(+EpbIremW+-8RCIY!~N#8 z;yE0YVIJ>gn>!qRvL9DdPz4rSJimdLI6A+kXX^Bp9Ahf4wwW$l_>hbw?wn8`^OWuh z4hZSEfL&07A2TI!ZoCnVSWk?dE4t!6mpHc4j=`+&dgVCB2U6$f=kp*6i;IabN-a@Y z#7pBL#l^+n*qGcB5veIGv|1j1FSjI9%~R?mfQjPJiH(eWXW7dp$Y7XDu3OQxD+Ude zygnllSUebXR&a1w2e9yj3)-Kxk~++ZsE7%EFKENt?x|~Qj^4RpPR=Y>vg#3^V@5%~ zd@Ao=9zwN5EJzU4)Fe@N-@)4rAA0lV1CGbfuaZ+^csLurrQP!d8FwDd=f1SK$fs|g z=kV23)6uXntCYStF)KlY3jS zAb)P=;YSiVBE{I4nR7}?xMs%_Idm#wVqy|V*4NhsZN6W%)I!>|MY2@n<;jfQ?)k68 z+T6&4Z7>Q^XmbBHFYm&_0+^RKQ(eu2M()($_w{*jGp<}7$VA%HLAaMh+o|npGg7n3X=yobrXSra zY@}2wdthl;70h*k>XWc9FGC3)U z+EPpO&K)f{e2&(1t}A<97Wd(!M-g8p-S?L&5eE9%Ona|gq-aosvDW=;L0Q?Q<>lqX z3_mVIMar6Nll3?QUaDV~HT4iMl+h!61RsQl==oSkNlHGy_;i-3#tb(ROo%%PukwSJ zmzR^1X?htuf#~#*0ZU~vaewE698qlkcz2Zlp^|eV-LFLRlyN<4f3I|0kvBMGT<;9_ zX>LsOS2RT?R!l&qMeq|~lSSw~w)DpU-iDMdZA5!s2=i;ajv({#3LrblQ#qG@ zCu%F_VpX+AK8CjYp(VAjL*sJO=K*Kx^;KX^f+tMR{#K#wR~wMZHxDZpTXYWkmJJTv zXCK{R`LRHTko3aE5~f_~h93 za0|V8{Jebz%E3`*KmPG+fCXTpn+s8U@%NN z4<9}Rl*tfDgSbDswY3$j4Z_^@h+FsW8I%O!=@ShM4!(|!Wn#+B$*~=->O|!e5fQ1D zOhpRJGUK1}-6(w+On{sF^1#KK<*&J|t*t>pL7knQu989PVo z!Kj54@$(!tnc?2c?`I@nK^p|@UY~=>-lSyVyfJh+Pur|~HpnC{LSp_~>fIrPKXImt zw)Xe_{#$qg{QN<#x9d}Q&BE6uW+NSV891e>5&Wz6bV2}OK_J6-SZWG!0F-%@BAmU2 zkbY`i&K31zW3F5HZdM@<)BOlQB-LPGNWehOw52$i7re8y$oLLqfWA3;;>n4LGf9v8 zX)K2;W0FQ+3!4wpmZKSs-DW#(Vo0VKMwA4N^ZG*=M%TShf7XBP+O@a^A!5bbBwCU(Bk$PJ8P{BC%ND~;UR4&tiU`=8N7S#(>ptV5in9y2 zzHBO`8@}a|TCD^Y@>x!>043q@9KeC8`k6lJm&z$AEzizUQc*>DyAy@B;mQwG+NJ5A z;~}%EG)3&nh<7K(BA%SlRCy{!%k%3phFIHGS}b-=QkS2fA5L!jzUiv-McSM$+g5a| z`5l(RbdbNynx@S&kuU8aevNn#Lq{mo`(AHj<9!vC$T_h>|Hq7X^H9MN5&f0a9J*B< z58$!!@lc{0suJNSc9^D3ZQZ{K<8?P^y!aD^rAjDTMnOTrz`&pb+XQbmA>Na;giEMd zDJgqy(njUMmyXA59E8q7RK#esBfayvn#X)ZDM_7D@GD~w2q1WkQ!rRSKtOD4?C9e- zPCYh<_j2(m!NCL(Ul_*gr%Q1Z5w5PT0MSTFOXp@~0dxiWQ&Cazn%7LO1rCS10#X+? zuj1HsZiJC66D&kIj={k}RV72-#cI+4AIzIjJ^=x_o6XWx+O8cakv+9YVO1Zn?QFRF z#!14Tl5U#9`C>}$?YH;iGsn}B?6*E9j5$&&iqDvqslZ4tZAaq%rWVF;Sem!(^4*@E zM#Xew&hi~@z-z$kvcTS>_7mv`{DMX1;HUBcIlrfoU=CKvBm1r7-G6q61?&~KlxSip z&Z$_qdo^GhyFbJnPeQ81%YcXQ4>1QG)A_@5Lk2>=^Mkp3kUhVD7*NL#9aOlT3-c6Ys-;!Bz9 zzk1_0H=DjeuK|*o=;msJro2W`s*o{9p?w6m#?tvybrky*W>;f^Q%VR{ydm42Jm}#{ z?bdN$h3^KYs1u;WvO3?kXdVOMp?7JkIDe(X3#|_}4`(o3UUSE6-o1PENmn$nIS-Bh zr>Ow}UGiF%hx3&Y&fId?k52OU$E=lm2DZlo@n1HMk&qn5(~QrJ9Vg>f8vql`SinQV zjv`=_CujfyiP4bw;5~Knh)(5JDpt{b%HLTI3pA>L@_$M(Pq^=oJsgl5!JjjOivYHX zC52C_q0oOxxIpu*+FDdm>8{0zF0+{&EODSbk6~lp-+835k8|>@(vc6XK3xq7b$Ox; zi!>cF=RSE?LSiH5*RB^(?|}B1V1%|5)iE!CE*9urrI55sb7 zZ@yYC0Re&6r>|{6q_=X0+R0ULw3z3=j{$Z%F)@*lKpF8RIw@&rbkvspmawq4)NO#v z3knKKN-jkZVCQZE5Q&y_tDWbTYgRZ}Ss%a^p$LBBE4~t}&`wC9X32G`oQev8Ter-p z*r3~K!D|Y#vV(6Qe*y_}dTIPqAO?+A5CZ9?ue)0fh)Azq+3#&wB(p)#mV8*2lOU1$ zg;GYZ-V4y-g2N9VJ}}A0HC<#7S%YQE`)TOwa}F{FgSJ$Lbj5KQT&JL*0IJ0B@S<*d zOh;E2ePh={*PazJ$P zqVDm6!2~S|AD~tcE20t-6WNHkU4Y;>`8ATk(s!uB#!_0ftGhew=?C@rMH!ibYG&`b z~z;K{4}-;V5Khn+#1%tax^u@oY1(%bQvM ztgI|R(_4IiD$Elh;AV!aoE^ji!udSOqLc{Zq+pyyKdYdPlbs{jHnxaJPUR%i*3(Ow zy2W>b_%iVUr1F!Ua$k(Wrfr}WXFmp7!gNtM)pU_kWoQ=+sde+iDpo>PjX7w;lfyq1 za{-yb?m{MX?YOoj3kfH^)7L}VHlkyp*pn?r#>KNy*yf6FqC zLnnv+J61*BDDi2CzYLo$BV}8I8QJE`@6n^|x2!{iP{@Au@C!-}V_eT=lCmd--CPFC zm18wJ=AVYYPl>$40u7Yo_|g$ZThKI<>ZxQB`;s)4Wv{5BV(U9MNOoNzWo_ru<#YgG zfGN9rU+UcnLwt8ZD-I1O>B^wx7~k+UXQQH$-`v6vI|1ilspiz6ZtD>xBqX@a_pp|8 ziO{?C)Su1YdrBt@y3ZIP1~b-7k4a~c$3L%VclUZkn<-LLj<@`tkPzJLauCav48(z1 zJO>j~_WSqnXVKFvF3!$*A?Z}q*l7}jCc$HwYeUPGC{gYkHKFta2Q<;09||$WLhbeI z-mth{JX$9~sR_S)RSb`_+H>v3$mBp`+OD9wx;nsT3mQ5RF8Zxb#fgf>mlv z*+NWG#d|@an*DtCFf{7yd1yK2k@?xPTP&bp2ckfT$o}O~*L+KB08h)-mdP=C7Ij~w zlfi#yGZ8kA> zI)Dh5!ZkU~x5{ozOs^_(cYS8%d%3(`3QGye5Av&5pIz-2mM&}dz#SR}d|N%a_PYi} znH8tmJ#&`_UqnLzW%ll|(*q!LT_TK+pC7M)3R6jZ?uTQUw9&x>5wbFy%wi-OgV`K0 zdVqn0{htwU*lC*xNI|H?&VQQg4>D|bDJdyg*w}85nDKLmW{C`&F*)R}!boe*j6k7! zCDYz8AXq(r{v13Vl<&cg1MT?drY1_db2jmcuIl&MKUjHrc^T$XQBi?~4HgJ=e=RXC zu5Vz#+%h1aQ}A&yqAtggQE$w&)PDS7&HQ3D`TXLL21S*zW+pWQez|J5j-W=K1S^2p zrSpV#BFyCByIE+^vY6nA zmbotEn3a>$%yQ%R+=ev9U z%uVZgOSyEfbGHWv1_tO&KFQ-zw z8#9qDUNOjh^RuV>st?yi>mD60?!rSVMt(`kTJJX&y@Wz;@cqVSk3CY4;UB5=8}^nM zXhTVWZVjYmX42ste8`n)caOBa!SEds=KW)!6=Yn2^ocBi;Bfz}U5AHbK z7ygHW^9%g|S@Rz?JM8Lp4uTWjPjeM$)6ij19|?HVAMEjGy9rCf|7=E!jKuc3jm}os zjnxBLF)yznw8(?D{~9ek?7=0v`+Fr68Kj(n$V}e*8 zMy+4^UL5*F_+F8~D`zR>DL}Bt#CEDH!_-u<5=bMT>iLWQV6&A9sLZw1EsL8Tx41_i z!Uw1MEEyS$`Q9?inz~nYsyDl*E2Ri)C@cSLvQE&5%Gj1FJttG1&40OJ`v-=Y+hgC*i*j;u3JAcc z(y2=ye|ixUa}`TM9KjBAo35T7Egc=#^O)FJ04wsEKy%{aM`1cJJhgSQHm>>YQg z{5x~!7%(Ire^htpoA>S=e|%2ZrdUp${3<3^FMC;JSv1N&_FQ7HgFQQu6vE2FLS;Sa z^=tPZjW~0TU_&%<87$?%bZqgitgP%pUs1Go_u_0X@5~413M~vzneKI(_aon5!wp?r znIa*m&4CalZ9{E2~_f_f;a*o^0UjFU?-+|)UzvXT=x4Tc4lb_j=6t>h$_yg{h zBk(POM?6Rve{mxh3PZk9UYYnD;+X!dpjs-3kZJXMxfQ@zrDn(5rD~vfmX+w$Mn*;k zU}<_UX;_vziJVH1iv)aOFY+%>O1m<>H2k%H*ySS||5Ns0epnsz0bc_?s4-tZ*~W0q zxfRWKC+=J(DmE@|YjaapEh#aP5h+-&aSunUZ*ADAJqSrMo<$qzW+pU9%`tp@Zx)b1U32U%UHWh+V{385vCg zAbiHy7XRzwM?|@?sIn{LjkuKXaN?j{liYXjup1Dckt8hg)%n*>X=f z?YZu{&)VVREZ>VtU%zK{4@EkZ0mgN|=>>>kTxhm$_<2A}$D05`k}FST0P6O%%J>L? z2~AG@fp#8$V8SoPk)BYXgyIpB%ap}OMrOp*4i8rwZx5XF#*0ZRJYw(GBcB}>z>pmL z#t=?};DI>goAEt>5_vL$j2ieU%%ic@If(>e0xQx+DAcaEiC9@#ZFWIWrPi z>&hhKAuSz9&^N6?N9G*cc;^m)+%<9|PrRnAV9gPW7nwy7Ohn|_Jv}{FS$f&WgfHd< zd_G6}Nu_KE6c%UNh5;$%zBOPnMrV!!fw(@q|A-G%jU)-!5NN>XYHmwpUnL`(8#4WG zbU--}1@;ukLgi|y>F7#GdJox1h!dAJ-&rew!1DO`Q&MY?-F!_GBd8@aovK;kjsCF#Y3M0dkSeWz3=G=kr|TN$a!s zVqd?88yJ+3I5|3k0nc73?P@=FQ8{!rl3q+g|hD`W2ze^bJI3A`LhZF)<7V^9Y1jJLgw#8qChkt-6WY zH5^ueWKxxMVVV2eEf@+}1&>{NOYd+wEnpf=N zc5TI~_16>z&~g^I7WM#*l3W5aNNpMuUh5)s+CBQZEOO%^DcefoPgVtO*(fRwtBbw= zS;%jY4|9Bv3q_(E*uHP;=B9Om*aluP8W*tHI;^=UC2iNNQyoQX=T2hv`?FY`z3m2% zw_d%ECV$>N-nA1;QGdJif-BW+$3o$>rb-$1p)*8XnCe8D4gDE8<{IDe&{ znA3G*JU@r^-{l0xbt>P8P6y#s==e*qKkXVQ%p&|P`~NQWVt6hc^4DHD!8XosEODyV z>)yi_vth*<%E3xI14l;KNu&YYSB4osl#*%&H7x+`i-)xU?Mf5=+~nee*jT4^P&V_o5HXjZfqd$! z=&-wn*j4Z8-=XF`898OxB>JD-aArU*;ODykBh}});HQ|`+uOH9G4Xu*8eXfxvlq!A zt^UGhs3MILUwq60RRp?0*}Xgz!J^WSr&@M)cCxZT?K7nEUr+b<5dwkmj#h43BSDG` z*H)PyYccuy@#lVYSYvSBl@fXP0Ffp-DoR3r5+A!f5d5nD2R2;Hq2SOqi6Q@=uptVV zg_6&Dy&*6$a8?0TG5JKirr(quYM%w{b%RS#GxBBsNY^*O7NLjodM@ z)W(!Ss3_Br)Qh0%y~Y^*`t|F%?fuUeP23P#i|Sz`?03q#Z8;wX(oMAW3E!tjh#t0b> z(gqR^WR=GiG(RS%k*i1wNe}DP;|+UZo&*r!%tKwO`;@pwf(f7`ofDa`70X}H^P?n9w2RDCW@j*E%8dOI0_VPbj)+L*h0}uyPWDt_G zzseJ2U=Tlkx@_v+v>bVHuZvYs^AMg>!`|`UW?B9%&Hb4Vg7xJz_stOeY|TGJnf>SJ zN!ZI3DYt%X@2{_|d5IZxT&qmR6U>~yftONadayCyTL>1*gMOqgm7h5E;<+YU?&&2U zM=+!R3h5tTLsafyQ3A!`!ly!VEK2C5KS2pQA^V^#@5$2lY}=7YP5i~s{scS}5FS|N zmWGPp@OrWjId<$kMwMR~9CGJ>ZjLXMv-cy}37zTYg!x(=ThWdXMIb7DafFDg!p5(O z=b|q_ys9zNbl5w2Pv10DbyoeGX0Q|;_5VBZ)Lk&T7CVk>2xzBd8yU${^B{c z7m`gHYHFll8{%@(8Emmnq*5ag$3U5$LeM|3Vc+)@Hq=P`FW5kWFB?1X>IWBC)l3EZ zk&H*YBW8%fgzD<*j~_pdj_MEI^Es#rchL9*w&GvR9h923MkT141jHD?VB`aEAZkcg zyE18QVQl}^od9_R)1=qb*GN$67VTF02_*ucLG!I7`RaOabAT_ZIn@Me;M_*SO}3oF zPg?KXpm&sTo}QYz6Okm3Yj0jL;-^KNv#0K8YHHfo-%omqAwc0URp(him;i8)W4eR+ zFW}&z^}M6I8x*39`s~|)a=zJFa}2f8-@t*QRMv}iJacZ)4*&;B;r|8>K#SzA1Cb8j z^#nM`h+*2a$!GQ9gRvl*)!^{OTJ+P_;5d(|Z#Q3dlaF0LhU0g!UbDG!=|Ox1O*KQJ zE}BP-SmjxD;s;P+kYbDe$xTSrebd$HG1dLR;%k8qZ@(-PahQ0v&R)d_2{auddO2-4 z|0sL#HapNSeuF=dIG_I6Pi}nhpviIf+b-!s8kN_=#MEhh8HfoG(%;1ZHlsR9l}oQf zmw^8c`~H22UqAb1Bz0RV?*5cN5B0InKBhh0FoE3vy5T}QeBE>3b*#uYQcKY5-8ye} zG^nvV;jj?Mm0KX?j}P_kX)KI+IjFKfR?IZRMS)E4`=!`yvwwcQr)}=m_OG)cL7K2U z-{0i^#@d{X?>qiIQ>JWJ@A+a-hv4}1;xz>FVqu)A}Zg@bSR z>>}z8XO7+M4EjIZyL8C9R)j4>J7xW#3qyfvFnNt;$$}Ompc9-Fs{crbFkj#Fg@KZT zVv9%u1R4C7^yKeNj?+P6*wh)l>u$TI&GkqRTLk|9Rd+Xs^Z&o@?$YnF&SK=>_~eTY zyl%UVt__quR$Lech6G41>EAvD3#?CJDgj7KgY@<_Z@1%<2mbP)x@Qe$MWckjSN%K) z83JmLh{rM20ij=M&6mGS18C-ym{^+QnR^W%$#3e65e@;DY1{JkzdQ&mz}%sTdOz%a z?9njhyYp+@_)B=oUC%A7o#202UJ*m+7bzes4wlYj$LmMUEdry0==pye6;xo+)|_E)=Ep)MfWoc^*0dwsMaLGZWybX>2yH&A8~jWyYV`>##O{?D(WHa)FO zIO)7MI>Bbl6*O@9PX6~z|9C@A%_0o4a7jr?cur--5%A4cdZ%> z!{ppD0~!we6*&cjiO%o3-8_`Az97Ar-hfM-5fR64Ypbu714o^KulEG@}1{Wc}1fuCR|42idSc+Af-ln{+wfT z0TZ)3)}y38p=0L~l-T3GTwf!zBJba&QKJ&=c(jo#?wTgHscx*)mdo@=PVUW7kv7#j z@RA{xnMP*TIkkQvGDTy>n?AF+=;$4C7+a`51RFbEF{!Ea9D=UHwwz&fpk9gwSa%xp zpiqY#$N3b|_m~e6)a~$96~}N)KHJQGX2htOBdcxO1b4DRkHMtwNN45}9$uwfi)wvU zRbL++Ny={1rcTNscJ#anV5fO9M~4pqHUpA8;u^=d`4Q=fBA zd&>Tx@_+iC&9_4(|XYb!m*~2Gyr63SK zt3gsSt4JL0Tqi?2uy)d;Hj0D^1IR}hY(Ae%w(}76a&akv$yUzCt?dEcg zPrT2!o2OIQXvP&ScieZa%2WduXIJ~({$gzG#+R)5;1D~y5fxA1v!0v~+xT+tDBf91 zpOi$5Z6i|sM6Ey^Vu3mIJZQH6NwcLRD$KCPa*{k9Hhp(QVRf&ZHcQ%z z3?w*w0GvUP7x!`aj|KJme6Qa;RWvYOCqN6w4sGqMtwVjHUd(4?$#~>t3V3drg+jei zCBQ`sWvSW(^D?7&l$HHkVZmO`bgU?Gl1k9eY40}Y7w3sQrY?6AEqEjWll4ilO!Ei# z^;RWJAQRVUbJeLm z-`G^0ejy?S98EwnmS>AnO|sOHk}6oWuyfti7SPdS{?(%vW_v)1CJ>>s5~=ij`q_J% zqa2fdb_jF;dk8}nA2X{Zo=}#G=fP^PBbf{M4HSez+ z3(lw{39b-=(+pnvXk2LqzWRKohux&?ZOMamCM{3XAGCub5_;N)-gKA@HTY)6jm+bd zS5Jf8)|Xl(c`UF>pZbHfNr1C2(vSv5fogf<0%Q-bb<7Ih`Qn>*B?F~}) zQ^S3bjL&LFYqR{fB}a68u#8wNr%K4tE)jTYLYyp7#p2c*!FV*1?2YL89yqFR@-9w?A|lQPS)^a-90nYPDbgd z>MQ)vp8Bv1vHNwS$0aZ${)}W%zSUF2m#TTD)Q8{Mvs((EneXL+rS>v8`e023Bo|;d zFQp-^Iq5gBrE_udn)#^e-I?)fJDR%1zo#I0_R)Gw3pOm0}L= z@tGfs%d7vK(h`IMr?h+~_XnQfzl^I9_mj$Cu$4ofA0I~z3T(Cy7lvR0qTs}oq?JSe zt4#tQh8U7SQ~o(G1z=SZ^^OM{`-cEIdQAk~5_r&bqx)twy_(biKzz5WP{Lk2Z}Z-5 zZMg~^sl0@k(3=RGsG3-|rQXH7C;InkE$1|001bN1Wyep+L?UedvD)Yz}cN-9YdKQw&${{Z2p-0T1V literal 0 HcmV?d00001 diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_images/k8s-happy-path.png b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_images/k8s-happy-path.png new file mode 100644 index 0000000000000000000000000000000000000000..d0e6a887cae953bc880f438d85639b80d4eceb2f GIT binary patch literal 17257 zcmbt*1yq!8_w67mCMrruBcXJIfPjE>Nen}ZfJ1jTn1~=q44o1JLrBNal0$ccbT>%D zeMbDn_y6v_>#lX*5n5^f2%)w74cqSSYxG`6?5=4WNKHrKPXcd#&LF|e|@ z!^TGnfna5ssH)rl^?L{w_!{S!_d)Vj#O${}tcUI2qE@hedFfF>7kNf#V1bN?xJE)_ z(+cj(T!Ha`M)U3UX`PEH%1NYxd>Iq$BJ-EwTEOvvFaa!F2Zd9;t{ICkT zdP(O-$Nost-Oi`#A|{+^{-l(J;)(Qci-fSf1;v$mEz_$4&3fOTwQSwt`*1ahpgc6u z6iq>O_I_0V+w}1F0w&5~vc%r@`@?VHgC-$v61T7SY@QJn(}z>R_N!V+)+HXcKKfX6 zH$L^_eM5`1*?>JqL{b&aVqax zAM54s;>9`jg$S8A|5Dwne;&_|6ekQGO1Z+xf4@kT(${sEsa<|!Oh#GLBuaQ}w?TqZ z1Xu05MoeOKz8>j4Vab#5$+TiJ|K1Kf4cUr>nZBz8?5#HsgiSvQtlC|zO5wRaz@7;U ztZ?HVDA;qQ82!>)cln{`O($Ph?ER-3z6V@<2@r^gsPr=tRp;T=*juX5f!Ouf+vriM z&~9Qh^$kA`cv@iIBW~_GB2y_%pTtnACv$wgnqhFhmRWti^dB6vo0;6bl783Dweela~$yeHXmoVRtoz$em%Z}e>vN3 zZ_H@j<5&FpknS%&A88n7(}3#@91nW_6NGw&LHJ<9>6@-=Ec15`J}geYe!aV zu=bUJ{h7?p6-rVT24iaCOWvKiiC_G$AAZ+@(KnuL23mc8-^{ZyMeyJ6V9VxsGh#b% zvRwXR{q*GM7KM=eQg8b9dUn?37d=Nr>u4|Cn{P*yP2&qjpiEo3@i&et`JR=diz}?z67~KcI~Ra z-|b&|+VFRU@R2|@87-m1g{0NhRY5^PpIa1$G1%5hB1sTPq8Qa{n>)2a{>W#6kbi%6 z!x|AnC!cr2%IwHQf6AyY$I(VK@3X4jXtLd^OQIxXdi^V&S}>T?>cT5Jb#2&<%JE84 z4dTgxeqFW*q#Cod)P8|`S$g5j49SFx(TK5PB8!e|X?8Y);7RJj!t(T#ehYeS6y=1S zjR$F%`>IboZB?GDk-R?X6aGF6NxGTY^~l?o(+#)S<)xuvRJ&+VmKID#Vx)+B@r#%b zKL>}h4T3GP;k}H;ox9ug?735cm;oyHveoM~G! z6=PlXHmBC-X5oQB$m89dVul}d4txDttCh21WVws_j!9p$Ir(3zbiv;tQ^XJ47ZUmL z_fL<;rji|ET()I)Drp{lGliK2w^N*MM2+Q)6!Xr{c}hSu9+K9f&2O6SR$SlS14#nWkQ4tlBbjXHuK;~r?rAWs)(!zmOMDmQ~9JxO<-;l6*R z{jQEe)X*Ud+!bn6q}b0eEON(s>0UMj#2fhq%TATWEa1Vy@wN{M5q*tEMl=zZfYc9FsE1bvm*;ZAp ze?mjzOC2HWsijEGKtnAQ9TD1%45BySrk&k(ec!2WR&^l%ZTnizji&GynnvY%axoRd zRr7J{$H()9dDQW_xp5EU)TxeykA|w6rTKfKA}X3gggK4cg@ukcIHcQ3EFwKilt0-#gBJi-p7yNA9y1d|+1Te)5=2e% zLrz0?+UHqU6wq=hwjb%!(~*RGPFQSixFaqvZEPy{1q;8Zzc{@)M9+v)If-3s;~m+N zNfoOMtA9~!nI4nlTD_!6XA6Mz0nK!6H&kZmYf?^exs$Y%LS@(Bq+}OVXm9lGp&~~f zRL%2f$Oy(ax@rP5OC?c*PfYuEX*}Y4#8jS@kzo%IFi+TSuI;e@5^8m4kvx6sV0%5x zB$Df!r&i!tTQ07OV5In>JZ`wP2j^R>^R*P1Q2k7f^{y1DYPB$wn?y?qGx_#zt?Iq67rE+ua?g-tq;O7{tHD{{ zjn1*k_1a1D!oPK}+4v&dbdfDcjOsoi_~)3de6~B}l$H1OYp1i%>Z39lK8lbeX66cm zS7xgriZ4C~R!#0zohkC^9mvTYXZjlrIXRnmJB<_~xdl(?1W&OY5D#uIIkHyWvc9~; zK&IRPz3{968QS4AK16rfe7PSnu*NWECT^{4$d9Hl=0C*|6XyXCZO;i{uTZ4i*4H3qnVqq&jo z*5?LZCjrK{Kghnb{GR;^xmv1J8@IC)%NCz~40co6>j~YGQ>>D{r!J_P&I2uKZRMKQ z;$Ph=WGX7V3P1W~`1k0)yJ>ZR4O-xr(7Kd{LPL>Z`z*dPAIo|u6ExkXeDOK<`zS(Y zIGLF>#waq25R6`w^GTMlFLm|o6JBRk0t1@hj1^g!;jL%S2?FTP3i}{$wan*YJMiYx ztmij-(vU1t5$5?5s~3*`$k?w; z%7)VNLhz}yKz@%h$;`~U@OWFhssb0gxA54(6o2GJB8qI~6ALqRC~I1@cr0Qv(Pyb3 zF5>ibRT(^XUQtmz`bqPCy!eVfIzanf^1BD$ImD-R?m_OVE!4V@r_s6Lsho)`3M$>F z@Oo>L(nY1~qaV+|D+m9LW;|X4X0F8DJLTUeqhK+?T7|B)HsbN(> z3;8W&UXEVZdDo78E<&#NGeqWML9+2aUx2*BeSfjxQg$#PfuCRBNMJ!keMB!zUw}1# zAjkS!1c8tJ{gy|GN);N^}LPaO-?n(jbl=Hezrw)4t(yp*Up z)i}A!4Z#an@c)sde!c=MD@PkNRfvUMSErT1&6yBI%Xi;JqQr>Bqvi&44gBrAzj*U} z#f&}SkAf}rI`g#oN=8Ozdz^IpvXq#Vom7%kPYl1qr`(&j@yaYM0`90^{>u?1^u**1*IAf!4-q!R zyAlgR`4+PC>kbZ3YJa_Q)TXt?hG@TpK)#4TTm`aicbtzT&qP=+LUwLKAonjO6a%ey z9z%dn{k}?M&i}85Vj^8|{bV4UWVeJoo%riZIGmklxgZHv5J(dxq=F3QI|}*ps&m8! z!392Ycp2h-DCpuB!F;P}e;jA=kZi*9hQ&v`1MNgxC(LG)u0fSe) zfcd;P(jK1zc7Gw)#l;2Xv>tb*5C=1g67=nkIehZKZwU!Mt6yW^F=cLu*X1C4jHNTn z&BEDGSNBYRHMay4u6rZ>dxwrYJD-b*i76-mSqkG5(oWfYs!faeo}Ubj#yk{cWLbM= zW@dNs@bvZd85kHY)sRqw~3?MT3+ep|qQWx*Q7(EZpbOa6U24{3XQQ!uUU z)b#Z9)RbDzi&bp}>F*+)of<1g?_p z{Pgtn3=C-1*Zcu+i;KPY?Fn$l#^DB&zt`6qap&!iw^#I1r?bqI(pVFNW>Z7TP_Im!!#EKfWut{!i?%+(^@SJvN zvQ7JNq6~9KdsBCcY`vv4sdSGOA8pN0zR|54H>BP$Gc!-E`RjgDj3gkT!`JZ)|BaD_dOOLSo-;Q=#+uDhm@bz0=J{;j=WikUjZS?i=pE7nXk zKD4(hMDDdH*xA{+x|VU^PleNr@@h=eKcuBi_ZSMw;n!XXv%@!u$#+asZpr6-pt1bG zWCcxs)zpdRYE1C{i)ePgQDTL%4^Tc_%9$&c+l*M}NxU z7y3w~eSmGD(E~$WzQ!`-edry{wK|nHe5H)j|K|`^4?P6(>NW&+e=~b)X=Bx^xw+Z& zvv_K6SO?26Gkf#BGqBpGUe?x~C2A&-0frrMg08zAdRxqk_KuDj8kO#4xr&}Glq|0E z?XgSb3J3S>v{Y4JMP`m^rm&BmXr|cp4@@zv_A@ZI@a1K9gPl5sldHDKdz}}&;2Cwg zJPkux1|nxJ0Nldh#KSb?y}8!Ne8*MIAroWcM=UIB%gZ4r)RF-UMuWZ6)^C4=hK4Tu z_@)p$+}-_v(|pqkA0MB8l!a_a=~Pl1E-L!wn*Zm|WJE;YnZDI^b?C`ZfhfljZft6b zZfa7`H~hTPV&v-TYG;=Z&pQnL+yPyBhz*5C#36UG9#G?IEbpfdTN|kM+98z18|E2S z(SHpZl};P(K?wvkjATvV?Iu#E*hwWAdFLohlZEXZ{X8C&$?#e&E0yn0`2oNh_D@Mk z5f>MqotY^pE=E4hWdw(-tE-Enp0~0rzqpu}mlyWnTWTsgc{Cyu&Y#B#N8givC?KFU zfyKDJ9}z*+vRGIbkcJ4`1fs^G#h#QKD5lT=1S{J%CCDDGR-%Y$$%r}x1JiN{p+=N zd5n%l$@-0k9LF(o*nPTlsKx;Ao$6;1*Eq*;h}>9Wo_N@g{qkFnPhtR&NjZ9Q0qQ+H zMT%7$a>}v}_$F>^)blW9ARTZBq#7Ea1wiz%B!q}|eB}5Ik?asZo!9m%e3>QoYZRrX?wqZJ*2 z)1v*@vwWp2=vOO9^^<5B4E5oaVnH^n=mo&o(yN*$w93^*Pap5#oTCW%d+=olWaF(T zPNt0wxHUMZug3$BH?W>G+=Sd|j6c(bw_2puOaJ|LFz#dP$(hBspQD9@`V}!o+|!7+ z$cx~AaGi4vhHd_0*ZTn*M7;kZ&HGQvZHXbByqII?4es>J67uI2fCm|3@Ezx1VSP@h zJQ*uP`2dRG-O0i_8NEj8+K#0^Tb$8!&wJ>SEM&K)o)XO{TycSR){i+iVB~A}cG)v8TTe2?Ngp&Pn>0 z;o;$T@7{r(Zxi?S?OTTLIXO9*nXS{C&m<)Y2?*l&>?FvLT~{^9EvM=Ubz_7)4*MpL z@K7j}$G4*fG;{et&*+@PZ0YU;av_Zj}%>H#CZxm$$gMcpxt>oJj+Zf`WpO@S%o)YLv`# z*N-x6jErUzl^!HK=2D7^utkc;)|3gxVHNd>gW;^YVJr;XVG$97gM$kVQ2tl!JUUH@ z!uw%$^1oRZBdGK~tNQ`_b3|SX041`mBM;spBO}uuE5OUer3#=yM<=VcUevi_oDr5S zRpN}l2}w=Q-=3uVw!%I%RA8c_q!cv!Y*d}0<$Y>Y6mj$NF&n^`E$9V8W=$F) zNyo#Zqk7x4LXF6tXqhR}HV!ySS@7(5Tb~|PRu*GcZJ*f^OvG5%YpSn7OK1|5nwo0T z!!$nh-F{IyR|`+FJCx2YjSKM;>@J+kmuYIk!U$}f8giBtA!|u|I|MEIvZVC>EC>?V zVzF3&BcW}3ttwvC=l5Wr0~@u*U=+fJwad)UKdd**u&r~#O-nml=X=-m48W1Tq{pqG zW*cqom|3~uwn;pZuhI_~(vy>uryB#06zV>wCE6`II=ZK)2O)TS zo_ex@ME zsm0{SEZ&EpOS#tjOvACMYfZFWBSL1XIM>^Ryt-s@_1NeR#M=gG)ozAJ&5_tyjryBc zYjwyile4qi?`0Jg^*cSVgh`Xd>Kv$bIp83Cny6~bn@ zo0XTREUYpAgfna?-}719z44);bh`d66JCQNfl=eH!NI{hwY`0lDJ?+L7TVwcLd%wF zpzRpVZPpL=P2X6=)=*y`yu4X$`gR)&d_uXo`BSdBiOHrGHtvhsM4EHn)rlJ}ERhMX z5cj&NpVe(eV9@zqPUB-fbWELyl(Y`Y(S}_O?FJY#Ei=(8@Nytq2WdEIRdw^ zzU1c3oAvee9v&WfUNcR1PD(TZ!MbJzsMGPOQQ(u12(YpJ+_P>=m5&B0Snl=v_wRw_ zexny}!DsW;WnE?EuM~I8|C@QOVjn-tmjz3zOr@cr0g$Ji`{z$uQW{I7p7HVQ3*bP!vSfZerJ$vy zwX4K265#90PN(luVtBZ-co^ShR!2TFJA29WDnJzVzeu%D3;GUFFhC=(jT)Rh)_7&S z6H8@k+^!YnB1S~X6}}-LsC|g7H?HE+<|2*4TXgk9>H?z1u}C`8F99jx>ZjvQF9C%j zRNpv@qnxUvHlpi^?5R`;Dk>^UOG`7Pro?R!a@znPr|Eim9Wh9q{*~)-o)ee6l*6sFlf}xaivD&__&jcUYEUw2P;nm?k zqH?(4ea=Q#y#MecQA+@cQDNigua+|#R@rdKd8Ft4(m%yqpQ)I3w7#1blFe}u!&CmS zUM@edMi%;(595~fqHylwjQ8I?)F7<5jbSNosaFX{v)@kXs+buR`I^6-x=J+8SXDxg z>vnGDDg!+^pI zPSwPO4}<>WmuG2bu%XlRML@c*ZkH@fGl*da+F)Zs%iAK_k6jL5PNxP2?oz*nOiqj( zbUeUJ5GMBfKN2us<o@bk&+b;lQB~Lc5LWMzK`UBwLdBk0U{@4W4 zzE*o{V=OH^iQ2SQ%fAHxk(o;JhVzq4moDMpl3qdJpa|wUu?83b(TZvbizKJJYO1P+ z+84#d#6(3!y?%`~k)7shU}CbkIo;UUr!EGx0R-~0yiBH$lZ&gjvy;-!LmU2zTl-b1 zOrhN@8Uc1_Z(koR9bMdGn_AwQ>x3*#IZ0zAz@5Zg)ay6DCME59T3A?!ii*m~$%%{C z|NNN{FwxsfWB9Zd#JsF8%F}A$Mm29P<^E_2zzyF=!g3U3WWYJ&V39Z=__3p+tE;P_ z5eekM1N?JVe(&Vq05>v{T{AH;0qn>YTMrU`At50EOO~T6;knr8dOouujVezMQ_~C@ z#P6^eS<9+h$;5|N3U)IvNJ_bHr{ad&2X`W<1n0t*_d_&Cp1Ft5uRMWEM%2ULArS_9 zW>1%M|7_FSD0E_CA~%5SNh_q=xKAR1EOHaJ2RIjXqc0dQqN-3qK^~mr_pu#^Kw{vp`?o@`+0C^o<&>RAn`({=O+nNR=~b>W&)I|$ z(&EUUc%7EN3l9w?iod~?Na4W5zW0*W_aPq5j20vc4KhN_sG7RKJrk zD@x@%Q~tf5KWpAPI5je5jgeBB^hlTOxn`wcRA|js|MT!d zqXBD2qe)cH$OxmFe7!aZr*$S*H761)RupPf4d2%V>3_V#o&Aw`y%cdp-z<<^FvF|j z9|nWnU)$ih{>MHP=A3Ri?)ajoY!1THzJ)I}T@$nTjU~Gua^gJ~ccsb~w&TTrW0o~S z1h_ezk00;X;7|;X5np5B`!#3>7;gEvR+!9u)P8ZrC#d(Ti7@8f-XJ6oTolt<>F@6c zqA9RZMMER~?C8ox$+LFdB5_44)LNKP)rO*?i{)PXscyS$_+KXHceXIot~`S+-r|R+ zV$Ya#FtG|C+BZtuRy;+UWraFUe#3kq<_5w}pN(}8<^5%jUSVIi z@D#~X1RO}6^4pO;j|(Y7F&s!PI9Bl3_g?{G^({h$IHAFk#c6|+ppg+5ty_ONu9z_X z_w@Z=h|n5w?T^s-onmNI5%f8W1Ui%D5SU$WKy(lB z*p8)VctYL*LXD0XKF)USS@p2aP*|r1>IvJ&oj$6=Y7i++*mVe|r>6tU#Ky)34hK20 zRX=-}34i045;O=L2=VbU^>tMii3P3V3F=>}O+jx0Zt>{*|A1r>0 z2LUHt_SUdY%6>dPquPy|fcWC0qXn>ZQjT=%9e{I_ty}eiKhb@x%F9b!{5|~~f)R#G z`uI5v79J7dJXLo!nFR7X@Zh6a7tE6ahw zL1SJg?Yvjg?(Xi|+M`Q-$k@A~_cXP%`fN4S)cPwuj(E%mzr@9{=)zf8wx!6j($l3m z5Sb~Eh93^8g@uJzuU^FyNlgY=2RpO1sH2MN?CV3s#xlPKbD<3BSp<+x{>1tDs?|`Q z_^OnYgv5ughKQ|TvdBkBl@Pnd)z#gsM-%QIJ&ViBcZ=6IooUE6Uz-XJouu=X$Vfk@ zTYk;|YNDa=dI4h~yhLo^+M~+1$bw91pD^2=5r+il#F?2H5a^>lfpB3DAXjT2lS`q) zj|dG-R{4(n;r$_kT^v6(E@ zKnBowG}{{+r)6Yhl$8zJs+kg6Y|S(SUo?+eK@7)~fLSwnZU|7#lyvW>PjZ=1xsZ7F z{;bDX&9d#{Oq&HJ1c5c`b7nGNo6S4vz9y>+UC)S+XVe27*<G_o>a<$C!0eF%W$Xway%AMOfk;ze&5|Wb3#trVY+$sma<+i_=+sL6<7=suVmz9^- zsc~Yae=0&Iy5HiJ*W11MuJWp;#PaGYGb?MjhMS>b>I<9h8#iw@AD=F5Y}@`Zx;Z_sIyoXd zk@Xz9Dsnjk(ed%D4Xh<9cD_XZ!0sowckg2F?e^D>%u{(OZ~WH1kD_j*70Zq=>sF2u zIS=SK^$iRx&oek=@jG$uS@08!wR#M_A;3cEVrwGr`Izq!-c5C>7N>ymNo=4^0AXn> zoPuE7|2i>s9x%ZZ++d4NS>0QgiYl+Wwy&3tyu7^b{m0pM{ETXu-`%o^f-X}N|uD|U!OvhSX#Nc!t2yQ(lMLnq}m%o8hDU^}i37os*oOFT0aOt`x3qDc2APooA|Lqp z;s&mIWY?#8_KJjV4w1cVN8^gPnSa}?G7foqbD2odNk)|4Yw>JbLh#g65eIxL${&|3;S3EP%3sWflmk& zA9QuFx|LOqGZiAe#MpqP^0OJCF^s&$+9w;|*j-@7v^zUx^i?8u%2KlP z?(Qxc>yrVjLdS6i*6isCz0!EOR?dm6Fl$kGRVA)kD=3HMUlgMP({uHA{V`JT;7 z76W6p$G$p2p2~+5CYanXxFJO1QpMxalPY|ny_7AWbH+GKG_`uOrmL0zena>vOHNtO z?qbKiG%_9@o}#OTHdG*KZ~;j}zLhho+^2n(lVQTxB?HIE@)5zJOqdzSKxN4aEwd9Sp0EoA5lGT~lqOJ4TRu%bT zav0>#Gh=eo7c;FqM!a&FC)=gYynsIXZMT3l_0vbYtKCDlZsk~3S#NPUT*CYTW4_OT zOu#=GfJ>MR0LV{6IIcXkYWyoHj(K*>g)z2&Uw!5h3si`|7DY7|k=)m>#CPCHAOQj#Z&Q#LnJWq4O_}KeJ1;LkA6O{e-Q7SbCH(lu zzQ5G@9ykvbnjb@?-N6wI(ALt5{_=&=7sO6CaB(x9=0ZU#0x#mXb#H7-@3>Y^C1PN) z-|j0ftdZI|FaT3io7;4rxmSk;^k742nj^wso`H4^n*s+*Nm!#m@qH`rWUYnVB9(zohE{h9VUlepX}oWQ+i!wJH#u13YARn0EhJbSjFS&`#^tZTG5f7C`jd_pPwB|27LB0@OmkLqXrBvKZ76+rr+AAV>mB^ z8GBWMq4V$-S7i_7SqrX-`GpqC^sgq=H1aPGGXxOygzTQmwncO zy8-N`9(I;%ZBg82m|}o1(Sy+YMVoY5x?m$vOQ(CF`iNR`IOqp%ncdITx)J1(RViW* z>I!VLFid>c26d07JU?GW8MtVxI< zA0;N0xRyGt2n?N-*Xm5tRbRi>?!8*YvlqToEGwe$T-cu1sGU@W?2w=@&zAJjqelx1 z3(xl$F-LLu0Vw4-$Ye$ib9Am@K;-E(4#*Rf!L75Exk22g2At7rt!-^OmF}gU*~(Se z{Z{8sdWVDrx&ECjy=(G$Me2%n89Hcbn;PV|A$Q%Qa4^gi;Et{Rml`toxwF{gapqAj zce=H;b-@8KrI&$38hp?wu}*Zw^0fvfR0|8nyV~*YAYGzS`7*zv!UG*jkH;w>Fyh>p zFbIhpiyF5zfe}S^rKY4v6M#rMIN@4oFvwX-qd9W8D_`Xm7sH--KU0vGN0?O1Hfz!? z0PIMieE5h(6g~!grocSL44v7*T&s!7tu0$XM;bJ=w9M+?pR!U6#TLS$BbPMeR1RUKPi{d#RwrfJ0e2IF){ORGgG6lUI*a%EOEoG>2t9{MGP7+;ABkC0%9(V0un(<$wFF**1 z{z|(SH0-}z9;&da)Gj?<+<${{XgHh2wX#vO3qLwKC9z(T{zLr%4_s|*8z%_PCbX)m zxGR4uB0~pe_2|zt{MHE1h4rlr0iF2LMJ-bwOzy5YZ1E{BdMg2!{@r@FKdf6jkujB?GqWsQWNl$V{ z+x+o(tY2gODMtE7@L*XZCLw>aEPvdf^WpthUgfv=!~D$}ar*zBSD~(fdTvdwD^%?q zIu9pfH8lFVZ*@`rxJs$|?iFc> zDe~X%09`{R%uZuf?aRAs6IEv$lb9kSey`If|NFL~qr6ly0mq%4o$@U-V|R>EM;!dW z+lKtV7r7t%FvhuWH3Kior2XV*FCNsF+Td1;U;3-~R{RPm-{q(s-pY0J%Cni4Flh(h z3+ezs4JiA6*3$mfD|KR=QZSnoC^S4iKHk$~x4)tH-@Q_xX$$hNJ}Z#p4TJpqrpYL@ zbO@cshvLE$F80m*B^c^4)sRF6n`L+Dukuc6?@cGAtBlgmk{~}d-?2>1y*5bi!1Oe9 zH`W`MVrtN7Xxuf0#(FhDt^0a;zD2>e=iw|B+AtU*&QryHXBRYrfYuXGc!C8iFatX! z_RpK3NS~>DZ{tTxZ9g=?xgV5-*F_5Yj67lE>hJw4yy*V4^!-UaGg$OaB_Tr3+bD zYF7o-I9S~qUslFdxd;c<NmwnlJLAcY;yJB+o7Fg0!jE zIHo%TOG`t1d|s^a{IAB!Qt&|G>|Ims2<6kU^Q833_@spoP#2DRW!Sa-6Vj2^h3zM=2={+$Z~Z_~}+ zUhYEcs*4w@0vaKt=WlsAx2+AVjzrtpRngcetAy+ zM=}rIP-bi`B<)4MYx%5pkqRDiiZ{Q4OSbfgp-e|PY)4#bWY`lObM;Rj&;F?0Eds*% z<(#jo!6oiXUqCUYG^vj}a|-lqXR9Uf;lqjjCTd|^*9Sh}yopW)GM$*3ERqSIZeH-Y z(p?NDqQBQ&v5jFy6+V&IpIk!WQ7};B=Z6UQ4b9lWtULZU!dLnERcUJP6yru|H#_1y zr0avQR({sQ3#twbqh}R6gitcAGpt^vN*dNxtj^eLho3qQ$+ z%R$A$LR+=V>?S{K?A13=Ns7 zeCzm3b9^M{JOzcPb7Zoic5!RR+0u2^%-l@lY1i5mSynU9%tmC@8BYEsbce4c*bjYi z26WEw^pUt;yseSFRe3}}fIqe-(eoMovODBHXC+>m+Qo~dvnniuCzT=x-I%STE(jEFu|7&%y;Bb4&^(+lUfD=mV2F2H6FGT!e~5vx>SQG!NxJr{0Lk5R6PdTZS+~FxN_vlA zTnz*gpf-Leo^RXGWBJXPgMr*Q%iwdluA`r&f$N(9L$(Hc&h$eArd>$>(_AAV;>)KB5V9ulj-Ve*swf z+2IOG4W!?U%YQiD(@BX5Z0-sR8)wfe{MGz02Q;&798H{ki}~(ON9U>5kiR1Egl7@8 zI@}i(=NUqN_PR{w&J_n#_yo>l(9DEO4@&1B3`5cL0_)~?v5Op*(PmDFzx%FKPEvGJ z;kGGvL|&9`;Q-uw7mHbnjn2e?l@->EKJs0uUJ@&FHPDB8b#{PKdv?5n1i(QrUK&Xu zD9~Z4wa~ukij!G3P0!QMxs<(CTs1~UNQj&uPHulLO7o;sGn!|$r2+rN&;aOS!p9%0 z1n|^X@v6T5fSY?FzdWZ^kF#v!_&6u(Ud_6y94>nWkC+wcajRd$Rd4Q6=L6lIa2K3R z9dwC|x0Dkik4&J5lkY%cIvN#=sF}o75C1*;FX$$3_motec^1!#9b?*gZkMseSq1#@^+5xaI#n`oW5B!a)&s}7r|1GP* z`cT>MK^=S+JNgqG1+Hr^zh2dO+<^@bDUH7pUMBn80uUU!)orrYtDg$f?0D3fh&z4# z<=g1LHkkp7J|R4S9rWt)F8-9U{C8Qdpx z+E;@Vhj=SuV70d>JSA=#4u#*I*9=i&=AYWEdnT?E4v-~x>#$z;Q0HtbWKr1fv1$d) zBL(OfFRMU9pMnwreSR`sJcmuMWUSB_wVK*gi(+Z1?r?c&O`gIErp3}~tnj^5}LbI??j^Ez`(2am0xHKGWQdv)CLz>ys;$s(#OdPhC->n6)J@2iaVlTU7` zh6wtmpMCunm*yW>Ra4Tv@Fhnq7c}!y0rH+Wqo_Ma$5+}50=7v>Iq^>pIBoCn4y*Qz zxXy^i1IBh+I|x|Rm{I~aFsB*<`og+0?fc)IL=oRTh+w|tSpRPLzS|5X)?LWt9mYG? zF>Gt^Sw!bwpNo)7W{B27AeDXp4-HGNZC)c^i3R?nfWXK8?r91Iz2ffzZh~IiP9Gb@ z!kzODsq<#<*T`h%`~TTbo{oG1df@runB{m(Z~@u=cPo4|!3PWsZ~0v#`B#g)7wn)} z@~x3$Rd!LhCdEjl{_fn_Nq*zn$yKeUV#$GHpMu#CMWIrIMqE&ivNFitz*imd`X9*} z@qM~B@s{G2mhaKtI^o0Nt}d!Z;cI%{T<^GixIS^Uoj1NyVOao;cANj{pJu8pAX{_F zw?2{5hZT_3LQJlh;F{bsi2@zT97R~77tY)Ky?={lOPv(w=X?^aX#>lvui2jdj|Qdx z(JMutTmJ#A2fC63Zu~QZ6xnd15y<}>!k<{B8uz~|pFtTc<_fAm!+zjaqNZeMg2KF( N7FT$dE&B4!{{o1#8z2Ax literal 0 HcmV?d00001 diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes.html new file mode 100644 index 00000000000..001f24b3613 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes.html @@ -0,0 +1,901 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+# NOTE! THIS FILE IS AUTOMATICALLY GENERATED AND WILL BE
+# OVERWRITTEN WHEN PREPARING DOCUMENTATION FOR THE PACKAGES.
+#
+# IF YOU WANT TO MODIFY THIS FILE, YOU SHOULD MODIFY THE TEMPLATE
+# `PROVIDER__INIT__PY_TEMPLATE.py.jinja2` IN the `dev/breeze/src/airflow_breeze/templates` DIRECTORY
+#
+from __future__ import annotations
+
+import packaging.version
+
+__all__ = ["__version__"]
+
+
[docs]__version__ = "8.1.1"
+ +try: + from airflow import __version__ as airflow_version +except ImportError: + from airflow.version import version as airflow_version + +if packaging.version.parse(packaging.version.parse(airflow_version).base_version) < packaging.version.parse( + "2.6.0" +): + raise RuntimeError( + f"The package `apache-airflow-providers-cncf-kubernetes:{__version__}` needs Apache Airflow 2.6.0+" + ) +
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/callbacks.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/callbacks.html new file mode 100644 index 00000000000..4523883d4e5 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/callbacks.html @@ -0,0 +1,972 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.callbacks — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.callbacks

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from enum import Enum
+from typing import Union
+
+import kubernetes.client as k8s
+import kubernetes_asyncio.client as async_k8s
+
+
[docs]client_type = Union[k8s.CoreV1Api, async_k8s.CoreV1Api]
+ + +
[docs]class ExecutionMode(str, Enum): + """Enum class for execution mode.""" + +
[docs] SYNC = "sync"
+
[docs] ASYNC = "async"
+ + +
[docs]class KubernetesPodOperatorCallback: + """`KubernetesPodOperator` callbacks methods. + + Currently, the callbacks methods are not called in the async mode, this support will be added + in the future. + """ + + @staticmethod +
[docs] def on_sync_client_creation(*, client: k8s.CoreV1Api, **kwargs) -> None: + """Invoke this callback after creating the sync client. + + :param client: the created `kubernetes.client.CoreV1Api` client. + """ + pass
+ + @staticmethod +
[docs] def on_pod_creation(*, pod: k8s.V1Pod, client: client_type, mode: str, **kwargs) -> None: + """Invoke this callback after creating the pod. + + :param pod: the created pod. + :param client: the Kubernetes client that can be used in the callback. + :param mode: the current execution mode, it's one of (`sync`, `async`). + """ + pass
+ + @staticmethod +
[docs] def on_pod_starting(*, pod: k8s.V1Pod, client: client_type, mode: str, **kwargs) -> None: + """Invoke this callback when the pod starts. + + :param pod: the started pod. + :param client: the Kubernetes client that can be used in the callback. + :param mode: the current execution mode, it's one of (`sync`, `async`). + """ + pass
+ + @staticmethod +
[docs] def on_pod_completion(*, pod: k8s.V1Pod, client: client_type, mode: str, **kwargs) -> None: + """Invoke this callback when the pod completes. + + :param pod: the completed pod. + :param client: the Kubernetes client that can be used in the callback. + :param mode: the current execution mode, it's one of (`sync`, `async`). + """ + pass
+ + @staticmethod +
[docs] def on_pod_cleanup(*, pod: k8s.V1Pod, client: client_type, mode: str, **kwargs): + """Invoke this callback after cleaning/deleting the pod. + + :param pod: the completed pod. + :param client: the Kubernetes client that can be used in the callback. + :param mode: the current execution mode, it's one of (`sync`, `async`). + """ + pass
+ + @staticmethod +
[docs] def on_operator_resuming( + *, pod: k8s.V1Pod, event: dict, client: client_type, mode: str, **kwargs + ) -> None: + """Invoke this callback when resuming the `KubernetesPodOperator` from deferred state. + + :param pod: the current state of the pod. + :param event: the returned event from the Trigger. + :param client: the Kubernetes client that can be used in the callback. + :param mode: the current execution mode, it's one of (`sync`, `async`). + """ + pass
+ + @staticmethod +
[docs] def progress_callback(*, line: str, client: client_type, mode: str, **kwargs) -> None: + """Invoke this callback to process pod container logs. + + :param line: the read line of log. + :param client: the Kubernetes client that can be used in the callback. + :param mode: the current execution mode, it's one of (`sync`, `async`). + """ + pass
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/decorators/kubernetes.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/decorators/kubernetes.html new file mode 100644 index 00000000000..65b1ded66a9 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/decorators/kubernetes.html @@ -0,0 +1,1013 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.decorators.kubernetes — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.decorators.kubernetes

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import base64
+import os
+import pickle
+import uuid
+from shlex import quote
+from tempfile import TemporaryDirectory
+from typing import TYPE_CHECKING, Callable, Sequence
+
+import dill
+from kubernetes.client import models as k8s
+
+from airflow.decorators.base import DecoratedOperator, TaskDecorator, task_decorator_factory
+from airflow.providers.cncf.kubernetes.operators.pod import KubernetesPodOperator
+from airflow.providers.cncf.kubernetes.python_kubernetes_script import (
+    write_python_script,
+)
+
+if TYPE_CHECKING:
+    from airflow.utils.context import Context
+
+_PYTHON_SCRIPT_ENV = "__PYTHON_SCRIPT"
+_PYTHON_INPUT_ENV = "__PYTHON_INPUT"
+
+
+def _generate_decoded_command(env_var: str, file: str) -> str:
+    return (
+        f'python -c "import base64, os;'
+        rf"x = base64.b64decode(os.environ[\"{env_var}\"]);"
+        rf'f = open(\"{file}\", \"wb\"); f.write(x); f.close()"'
+    )
+
+
+def _read_file_contents(filename: str) -> str:
+    with open(filename, "rb") as script_file:
+        return base64.b64encode(script_file.read()).decode("utf-8")
+
+
+class _KubernetesDecoratedOperator(DecoratedOperator, KubernetesPodOperator):
+    custom_operator_name = "@task.kubernetes"
+
+    # `cmds` and `arguments` are used internally by the operator
+    template_fields: Sequence[str] = tuple(
+        {"op_args", "op_kwargs", *KubernetesPodOperator.template_fields} - {"cmds", "arguments"}
+    )
+
+    # Since we won't mutate the arguments, we should just do the shallow copy
+    # there are some cases we can't deepcopy the objects (e.g protobuf).
+    shallow_copy_attrs: Sequence[str] = ("python_callable",)
+
+    def __init__(self, namespace: str = "default", use_dill: bool = False, **kwargs) -> None:
+        self.use_dill = use_dill
+        super().__init__(
+            namespace=namespace,
+            name=kwargs.pop("name", f"k8s_airflow_pod_{uuid.uuid4().hex}"),
+            cmds=["placeholder-command"],
+            **kwargs,
+        )
+
+    def _generate_cmds(self) -> list[str]:
+        script_filename = "/tmp/script.py"
+        input_filename = "/tmp/script.in"
+        output_filename = "/airflow/xcom/return.json"
+
+        write_local_script_file_cmd = (
+            f"{_generate_decoded_command(quote(_PYTHON_SCRIPT_ENV), quote(script_filename))}"
+        )
+        write_local_input_file_cmd = (
+            f"{_generate_decoded_command(quote(_PYTHON_INPUT_ENV), quote(input_filename))}"
+        )
+        make_xcom_dir_cmd = "mkdir -p /airflow/xcom"
+        exec_python_cmd = f"python {script_filename} {input_filename} {output_filename}"
+        return [
+            "bash",
+            "-cx",
+            (
+                f"{write_local_script_file_cmd} && "
+                f"{write_local_input_file_cmd} && "
+                f"{make_xcom_dir_cmd} && "
+                f"{exec_python_cmd}"
+            ),
+        ]
+
+    def execute(self, context: Context):
+        with TemporaryDirectory(prefix="venv") as tmp_dir:
+            pickling_library = dill if self.use_dill else pickle
+            script_filename = os.path.join(tmp_dir, "script.py")
+            input_filename = os.path.join(tmp_dir, "script.in")
+
+            with open(input_filename, "wb") as file:
+                pickling_library.dump({"args": self.op_args, "kwargs": self.op_kwargs}, file)
+
+            py_source = self.get_python_source()
+            jinja_context = {
+                "op_args": self.op_args,
+                "op_kwargs": self.op_kwargs,
+                "pickling_library": pickling_library.__name__,
+                "python_callable": self.python_callable.__name__,
+                "python_callable_source": py_source,
+                "string_args_global": False,
+            }
+            write_python_script(jinja_context=jinja_context, filename=script_filename)
+
+            self.env_vars = [
+                *self.env_vars,
+                k8s.V1EnvVar(name=_PYTHON_SCRIPT_ENV, value=_read_file_contents(script_filename)),
+                k8s.V1EnvVar(name=_PYTHON_INPUT_ENV, value=_read_file_contents(input_filename)),
+            ]
+
+            self.cmds = self._generate_cmds()
+            return super().execute(context)
+
+
+
[docs]def kubernetes_task( + python_callable: Callable | None = None, + multiple_outputs: bool | None = None, + **kwargs, +) -> TaskDecorator: + """Kubernetes operator decorator. + + This wraps a function to be executed in K8s using KubernetesPodOperator. + Also accepts any argument that DockerOperator will via ``kwargs``. Can be + reused in a single DAG. + + :param python_callable: Function to decorate + :param multiple_outputs: if set, function return value will be + unrolled to multiple XCom values. Dict will unroll to xcom values with + keys as XCom keys. Defaults to False. + """ + return task_decorator_factory( + python_callable=python_callable, + multiple_outputs=multiple_outputs, + decorated_operator_class=_KubernetesDecoratedOperator, + **kwargs, + )
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/executors/kubernetes_executor.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/executors/kubernetes_executor.html new file mode 100644 index 00000000000..b99d7ba6c19 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/executors/kubernetes_executor.html @@ -0,0 +1,1658 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.executors.kubernetes_executor — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.executors.kubernetes_executor

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""
+KubernetesExecutor.
+
+.. seealso::
+    For more information on how the KubernetesExecutor works, take a look at the guide:
+    :doc:`/kubernetes_executor`
+"""
+
+from __future__ import annotations
+
+import contextlib
+import json
+import logging
+import multiprocessing
+import time
+from collections import Counter, defaultdict
+from contextlib import suppress
+from datetime import datetime
+from queue import Empty, Queue
+from typing import TYPE_CHECKING, Any, Sequence
+
+from kubernetes.dynamic import DynamicClient
+from sqlalchemy import select, update
+
+from airflow.providers.cncf.kubernetes.pod_generator import PodMutationHookException, PodReconciliationError
+from airflow.stats import Stats
+
+try:
+    from airflow.cli.cli_config import (
+        ARG_DAG_ID,
+        ARG_EXECUTION_DATE,
+        ARG_OUTPUT_PATH,
+        ARG_SUBDIR,
+        ARG_VERBOSE,
+        ActionCommand,
+        Arg,
+        GroupCommand,
+        lazy_load_command,
+        positive_int,
+    )
+except ImportError:
+    try:
+        from airflow import __version__ as airflow_version
+    except ImportError:
+        from airflow.version import version as airflow_version
+
+    import packaging.version
+
+    from airflow.exceptions import AirflowOptionalProviderFeatureException
+
+
[docs] base_version = packaging.version.parse(airflow_version).base_version
+ + if packaging.version.parse(base_version) < packaging.version.parse("2.7.0"): + raise AirflowOptionalProviderFeatureException( + "Kubernetes Executor from CNCF Provider should only be used with Airflow 2.7.0+.\n" + f"This is Airflow {airflow_version} and Kubernetes and CeleryKubernetesExecutor are " + f"available in the 'airflow.executors' package. You should not use " + f"the provider's executors in this version of Airflow." + ) + raise +from airflow.configuration import conf +from airflow.executors.base_executor import BaseExecutor +from airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types import ( + ADOPTED, + POD_EXECUTOR_DONE_KEY, +) +from airflow.providers.cncf.kubernetes.kube_config import KubeConfig +from airflow.providers.cncf.kubernetes.kubernetes_helper_functions import annotations_to_key +from airflow.utils.event_scheduler import EventScheduler +from airflow.utils.log.logging_mixin import remove_escape_codes +from airflow.utils.session import NEW_SESSION, provide_session +from airflow.utils.state import TaskInstanceState + +if TYPE_CHECKING: + import argparse + + from kubernetes import client + from kubernetes.client import models as k8s + from sqlalchemy.orm import Session + + from airflow.executors.base_executor import CommandType + from airflow.models.taskinstance import TaskInstance + from airflow.models.taskinstancekey import TaskInstanceKey + from airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types import ( + KubernetesJobType, + KubernetesResultsType, + ) + from airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils import ( + AirflowKubernetesScheduler, + ) + + +# CLI Args +
[docs]ARG_NAMESPACE = Arg( + ("--namespace",), + default=conf.get("kubernetes_executor", "namespace"), + help="Kubernetes Namespace. Default value is `[kubernetes] namespace` in configuration.", +)
+ +
[docs]ARG_MIN_PENDING_MINUTES = Arg( + ("--min-pending-minutes",), + default=30, + type=positive_int(allow_zero=False), + help=( + "Pending pods created before the time interval are to be cleaned up, " + "measured in minutes. Default value is 30(m). The minimum value is 5(m)." + ), +)
+ +# CLI Commands +
[docs]KUBERNETES_COMMANDS = ( + ActionCommand( + name="cleanup-pods", + help=( + "Clean up Kubernetes pods " + "(created by KubernetesExecutor/KubernetesPodOperator) " + "in evicted/failed/succeeded/pending states" + ), + func=lazy_load_command("airflow.cli.commands.kubernetes_command.cleanup_pods"), + args=(ARG_NAMESPACE, ARG_MIN_PENDING_MINUTES, ARG_VERBOSE), + ), + ActionCommand( + name="generate-dag-yaml", + help="Generate YAML files for all tasks in DAG. Useful for debugging tasks without " + "launching into a cluster", + func=lazy_load_command("airflow.cli.commands.kubernetes_command.generate_pod_yaml"), + args=(ARG_DAG_ID, ARG_EXECUTION_DATE, ARG_SUBDIR, ARG_OUTPUT_PATH, ARG_VERBOSE), + ), +)
+ + +
[docs]class KubernetesExecutor(BaseExecutor): + """Executor for Kubernetes.""" + +
[docs] RUNNING_POD_LOG_LINES = 100
+
[docs] supports_ad_hoc_ti_run: bool = True
+ + def __init__(self): + self.kube_config = KubeConfig() + self._manager = multiprocessing.Manager() + self.task_queue: Queue[KubernetesJobType] = self._manager.Queue() + self.result_queue: Queue[KubernetesResultsType] = self._manager.Queue() + self.kube_scheduler: AirflowKubernetesScheduler | None = None + self.kube_client: client.CoreV1Api | None = None + self.scheduler_job_id: str | None = None + self.event_scheduler: EventScheduler | None = None + self.last_handled: dict[TaskInstanceKey, float] = {} + self.kubernetes_queue: str | None = None + self.task_publish_retries: Counter[TaskInstanceKey] = Counter() + self.task_publish_max_retries = conf.getint("kubernetes", "task_publish_max_retries", fallback=0) + super().__init__(parallelism=self.kube_config.parallelism) + + def _list_pods(self, query_kwargs): + query_kwargs["header_params"] = { + "Accept": "application/json;as=PartialObjectMetadataList;v=v1;g=meta.k8s.io" + } + dynamic_client = DynamicClient(self.kube_client.api_client) + pod_resource = dynamic_client.resources.get(api_version="v1", kind="Pod") + if self.kube_config.multi_namespace_mode: + if self.kube_config.multi_namespace_mode_namespace_list: + namespaces = self.kube_config.multi_namespace_mode_namespace_list + else: + namespaces = [None] + else: + namespaces = [self.kube_config.kube_namespace] + + pods = [] + for namespace in namespaces: + # Dynamic Client list pods is throwing TypeError when there are no matching pods to return + # This bug was fixed in MR https://github.com/kubernetes-client/python/pull/2155 + # TODO: Remove the try-except clause once we upgrade the K8 Python client version which + # includes the above MR + try: + pods.extend( + dynamic_client.get(resource=pod_resource, namespace=namespace, **query_kwargs).items + ) + except TypeError: + continue + + return pods + + def _make_safe_label_value(self, input_value: str | datetime) -> str: + """ + Normalize a provided label to be of valid length and characters. + + See airflow.providers.cncf.kubernetes.pod_generator.make_safe_label_value for more details. + """ + # airflow.providers.cncf.kubernetes is an expensive import, locally import it here to + # speed up load times of the kubernetes_executor module. + from airflow.providers.cncf.kubernetes import pod_generator + + if isinstance(input_value, datetime): + return pod_generator.datetime_to_label_safe_datestring(input_value) + return pod_generator.make_safe_label_value(input_value) + + @provide_session +
[docs] def clear_not_launched_queued_tasks(self, session: Session = NEW_SESSION) -> None: + """ + Clear tasks that were not yet launched, but were previously queued. + + Tasks can end up in a "Queued" state when a rescheduled/deferred operator + comes back up for execution (with the same try_number) before the + pod of its previous incarnation has been fully removed (we think). + + It's also possible when an executor abruptly shuts down (leaving a non-empty + task_queue on that executor), but that scenario is handled via normal adoption. + + This method checks each of our queued tasks to see if the corresponding pod + is around, and if not, and there's no matching entry in our own + task_queue, marks it for re-execution. + """ + if TYPE_CHECKING: + assert self.kube_client + from airflow.models.taskinstance import TaskInstance + + with Stats.timer("kubernetes_executor.clear_not_launched_queued_tasks.duration"): + self.log.debug("Clearing tasks that have not been launched") + query = select(TaskInstance).where( + TaskInstance.state == TaskInstanceState.QUEUED, TaskInstance.queued_by_job_id == self.job_id + ) + if self.kubernetes_queue: + query = query.where(TaskInstance.queue == self.kubernetes_queue) + queued_tis: list[TaskInstance] = session.scalars(query).all() + self.log.info("Found %s queued task instances", len(queued_tis)) + + # Go through the "last seen" dictionary and clean out old entries + allowed_age = self.kube_config.worker_pods_queued_check_interval * 3 + for key, timestamp in list(self.last_handled.items()): + if time.time() - timestamp > allowed_age: + del self.last_handled[key] + + if not queued_tis: + return + + # airflow worker label selector batch call + kwargs = {"label_selector": f"airflow-worker={self._make_safe_label_value(str(self.job_id))}"} + if self.kube_config.kube_client_request_args: + kwargs.update(self.kube_config.kube_client_request_args) + pod_list = self._list_pods(kwargs) + + # create a set against pod query label fields + label_search_set = set() + for pod in pod_list: + dag_id = pod.metadata.labels.get("dag_id", None) + task_id = pod.metadata.labels.get("task_id", None) + airflow_worker = pod.metadata.labels.get("airflow-worker", None) + map_index = pod.metadata.labels.get("map_index", None) + run_id = pod.metadata.labels.get("run_id", None) + execution_date = pod.metadata.labels.get("execution_date", None) + if dag_id is None or task_id is None or airflow_worker is None: + continue + label_search_base_str = f"dag_id={dag_id},task_id={task_id},airflow-worker={airflow_worker}" + if map_index is not None: + label_search_base_str += f",map_index={map_index}" + if run_id is not None: + label_search_str = f"{label_search_base_str},run_id={run_id}" + label_search_set.add(label_search_str) + if execution_date is not None: + label_search_str = f"{label_search_base_str},execution_date={execution_date}" + label_search_set.add(label_search_str) + + for ti in queued_tis: + self.log.debug("Checking task instance %s", ti) + + # Check to see if we've handled it ourselves recently + if ti.key in self.last_handled: + continue + + # Build the pod selector + base_label_selector = ( + f"dag_id={self._make_safe_label_value(ti.dag_id)}," + f"task_id={self._make_safe_label_value(ti.task_id)}," + f"airflow-worker={self._make_safe_label_value(str(ti.queued_by_job_id))}" + ) + if ti.map_index >= 0: + # Old tasks _couldn't_ be mapped, so we don't have to worry about compat + base_label_selector += f",map_index={ti.map_index}" + + # Try run_id first + label_search_str = f"{base_label_selector},run_id={self._make_safe_label_value(ti.run_id)}" + if label_search_str in label_search_set: + continue + # Fallback to old style of using execution_date + label_search_str = ( + f"{base_label_selector},execution_date={self._make_safe_label_value(ti.execution_date)}" + ) + if label_search_str in label_search_set: + continue + self.log.info("TaskInstance: %s found in queued state but was not launched, rescheduling", ti) + session.execute( + update(TaskInstance) + .where( + TaskInstance.dag_id == ti.dag_id, + TaskInstance.task_id == ti.task_id, + TaskInstance.run_id == ti.run_id, + TaskInstance.map_index == ti.map_index, + ) + .values(state=TaskInstanceState.SCHEDULED) + )
+ +
[docs] def start(self) -> None: + """Start the executor.""" + self.log.info("Start Kubernetes executor") + self.scheduler_job_id = str(self.job_id) + self.log.debug("Start with scheduler_job_id: %s", self.scheduler_job_id) + from airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils import ( + AirflowKubernetesScheduler, + ) + from airflow.providers.cncf.kubernetes.kube_client import get_kube_client + + self.kube_client = get_kube_client() + self.kube_scheduler = AirflowKubernetesScheduler( + kube_config=self.kube_config, + result_queue=self.result_queue, + kube_client=self.kube_client, + scheduler_job_id=self.scheduler_job_id, + ) + self.event_scheduler = EventScheduler() + + self.event_scheduler.call_regular_interval( + self.kube_config.worker_pods_queued_check_interval, + self.clear_not_launched_queued_tasks, + ) + # We also call this at startup as that's the most likely time to see + # stuck queued tasks + self.clear_not_launched_queued_tasks()
+ +
[docs] def execute_async( + self, + key: TaskInstanceKey, + command: CommandType, + queue: str | None = None, + executor_config: Any | None = None, + ) -> None: + """Execute task asynchronously.""" + if TYPE_CHECKING: + assert self.task_queue + + if self.log.isEnabledFor(logging.DEBUG): + self.log.debug("Add task %s with command %s, executor_config %s", key, command, executor_config) + else: + self.log.info("Add task %s with command %s", key, command) + + from airflow.providers.cncf.kubernetes.pod_generator import PodGenerator + + try: + kube_executor_config = PodGenerator.from_obj(executor_config) + except Exception: + self.log.error("Invalid executor_config for %s. Executor_config: %s", key, executor_config) + self.fail(key=key, info="Invalid executor_config passed") + return + + if executor_config: + pod_template_file = executor_config.get("pod_template_file", None) + else: + pod_template_file = None + self.event_buffer[key] = (TaskInstanceState.QUEUED, self.scheduler_job_id) + self.task_queue.put((key, command, kube_executor_config, pod_template_file)) + # We keep a temporary local record that we've handled this so we don't + # try and remove it from the QUEUED state while we process it + self.last_handled[key] = time.time()
+ +
[docs] def sync(self) -> None: + """Synchronize task state.""" + if TYPE_CHECKING: + assert self.scheduler_job_id + assert self.kube_scheduler + assert self.kube_config + assert self.result_queue + assert self.task_queue + assert self.event_scheduler + + if self.running: + self.log.debug("self.running: %s", self.running) + if self.queued_tasks: + self.log.debug("self.queued: %s", self.queued_tasks) + self.kube_scheduler.sync() + + last_resource_version: dict[str, str] = defaultdict(lambda: "0") + with contextlib.suppress(Empty): + while True: + results = self.result_queue.get_nowait() + try: + key, state, pod_name, namespace, resource_version = results + last_resource_version[namespace] = resource_version + self.log.info("Changing state of %s to %s", results, state) + try: + self._change_state(key, state, pod_name, namespace) + except Exception as e: + self.log.exception( + "Exception: %s when attempting to change state of %s to %s, re-queueing.", + e, + results, + state, + ) + self.result_queue.put(results) + finally: + self.result_queue.task_done() + + from airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils import ResourceVersion + + resource_instance = ResourceVersion() + for ns in resource_instance.resource_version: + resource_instance.resource_version[ns] = ( + last_resource_version[ns] or resource_instance.resource_version[ns] + ) + + from kubernetes.client.rest import ApiException + + with contextlib.suppress(Empty): + for _ in range(self.kube_config.worker_pods_creation_batch_size): + task = self.task_queue.get_nowait() + + try: + key, command, kube_executor_config, pod_template_file = task + self.kube_scheduler.run_next(task) + self.task_publish_retries.pop(key, None) + except PodReconciliationError as e: + self.log.exception( + "Pod reconciliation failed, likely due to kubernetes library upgrade. " + "Try clearing the task to re-run.", + ) + self.fail(task[0], e) + except ApiException as e: + body = json.loads(e.body) + retries = self.task_publish_retries[key] + # In case of exceeded quota errors, requeue the task as per the task_publish_max_retries + if ( + str(e.status) == "403" + and "exceeded quota" in body["message"] + and (self.task_publish_max_retries == -1 or retries < self.task_publish_max_retries) + ): + self.log.warning( + "[Try %s of %s] Kube ApiException for Task: (%s). Reason: %r. Message: %s", + self.task_publish_retries[key] + 1, + self.task_publish_max_retries, + key, + e.reason, + body["message"], + ) + self.task_queue.put(task) + self.task_publish_retries[key] = retries + 1 + else: + self.log.error("Pod creation failed with reason %r. Failing task", e.reason) + key, _, _, _ = task + self.fail(key, e) + self.task_publish_retries.pop(key, None) + except PodMutationHookException as e: + key, _, _, _ = task + self.log.error( + "Pod Mutation Hook failed for the task %s. Failing task. Details: %s", + key, + e.__cause__, + ) + self.fail(key, e) + finally: + self.task_queue.task_done() + + # Run any pending timed events + next_event = self.event_scheduler.run(blocking=False) + self.log.debug("Next timed event is in %f", next_event)
+ + @provide_session + def _change_state( + self, + key: TaskInstanceKey, + state: TaskInstanceState | str | None, + pod_name: str, + namespace: str, + session: Session = NEW_SESSION, + ) -> None: + if TYPE_CHECKING: + assert self.kube_scheduler + + if state == ADOPTED: + # When the task pod is adopted by another executor, + # then remove the task from the current executor running queue. + try: + self.running.remove(key) + except KeyError: + self.log.debug("TI key not in running: %s", key) + return + + if state == TaskInstanceState.RUNNING: + self.event_buffer[key] = state, None + return + + if self.kube_config.delete_worker_pods: + if state != TaskInstanceState.FAILED or self.kube_config.delete_worker_pods_on_failure: + self.kube_scheduler.delete_pod(pod_name=pod_name, namespace=namespace) + self.log.info("Deleted pod: %s in namespace %s", key, namespace) + else: + self.kube_scheduler.patch_pod_executor_done(pod_name=pod_name, namespace=namespace) + self.log.info("Patched pod %s in namespace %s to mark it as done", key, namespace) + + try: + self.running.remove(key) + except KeyError: + self.log.debug("TI key not in running, not adding to event_buffer: %s", key) + + # If we don't have a TI state, look it up from the db. event_buffer expects the TI state + if state is None: + from airflow.models.taskinstance import TaskInstance + + state = session.scalar(select(TaskInstance.state).where(TaskInstance.filter_for_tis([key]))) + state = TaskInstanceState(state) if state else None + + self.event_buffer[key] = state, None + + @staticmethod + def _get_pod_namespace(ti: TaskInstance): + pod_override = ti.executor_config.get("pod_override") + namespace = None + with suppress(Exception): + namespace = pod_override.metadata.namespace + return namespace or conf.get("kubernetes_executor", "namespace") + +
[docs] def get_task_log(self, ti: TaskInstance, try_number: int) -> tuple[list[str], list[str]]: + messages = [] + log = [] + try: + from airflow.providers.cncf.kubernetes.kube_client import get_kube_client + from airflow.providers.cncf.kubernetes.pod_generator import PodGenerator + + client = get_kube_client() + + messages.append(f"Attempting to fetch logs from pod {ti.hostname} through kube API") + selector = PodGenerator.build_selector_for_k8s_executor_pod( + dag_id=ti.dag_id, + task_id=ti.task_id, + try_number=try_number, + map_index=ti.map_index, + run_id=ti.run_id, + airflow_worker=ti.queued_by_job_id, + ) + namespace = self._get_pod_namespace(ti) + pod_list = client.list_namespaced_pod( + namespace=namespace, + label_selector=selector, + ).items + if not pod_list: + raise RuntimeError("Cannot find pod for ti %s", ti) + elif len(pod_list) > 1: + raise RuntimeError("Found multiple pods for ti %s: %s", ti, pod_list) + res = client.read_namespaced_pod_log( + name=pod_list[0].metadata.name, + namespace=namespace, + container="base", + follow=False, + tail_lines=self.RUNNING_POD_LOG_LINES, + _preload_content=False, + ) + for line in res: + log.append(remove_escape_codes(line.decode())) + if log: + messages.append("Found logs through kube API") + except Exception as e: + messages.append(f"Reading from k8s pod logs failed: {e}") + return messages, ["\n".join(log)]
+ +
[docs] def try_adopt_task_instances(self, tis: Sequence[TaskInstance]) -> Sequence[TaskInstance]: + with Stats.timer("kubernetes_executor.adopt_task_instances.duration"): + # Always flush TIs without queued_by_job_id + tis_to_flush = [ti for ti in tis if not ti.queued_by_job_id] + scheduler_job_ids = {ti.queued_by_job_id for ti in tis} + tis_to_flush_by_key = {ti.key: ti for ti in tis if ti.queued_by_job_id} + kube_client: client.CoreV1Api = self.kube_client + for scheduler_job_id in scheduler_job_ids: + scheduler_job_id = self._make_safe_label_value(str(scheduler_job_id)) + # We will look for any pods owned by the no-longer-running scheduler, + # but will exclude only successful pods, as those TIs will have a terminal state + # and not be up for adoption! + # Those workers that failed, however, are okay to adopt here as their TI will + # still be in queued. + query_kwargs = { + "field_selector": "status.phase!=Succeeded", + "label_selector": ( + "kubernetes_executor=True," + f"airflow-worker={scheduler_job_id},{POD_EXECUTOR_DONE_KEY}!=True" + ), + } + pod_list = self._list_pods(query_kwargs) + for pod in pod_list: + self.adopt_launched_task(kube_client, pod, tis_to_flush_by_key) + self._adopt_completed_pods(kube_client) + tis_to_flush.extend(tis_to_flush_by_key.values()) + return tis_to_flush
+ +
[docs] def cleanup_stuck_queued_tasks(self, tis: list[TaskInstance]) -> list[str]: + """ + Handle remnants of tasks that were failed because they were stuck in queued. + + Tasks can get stuck in queued. If such a task is detected, it will be marked + as `UP_FOR_RETRY` if the task instance has remaining retries or marked as `FAILED` + if it doesn't. + + :param tis: List of Task Instances to clean up + :return: List of readable task instances for a warning message + """ + from airflow.providers.cncf.kubernetes.pod_generator import PodGenerator + + if TYPE_CHECKING: + assert self.kube_client + assert self.kube_scheduler + readable_tis = [] + for ti in tis: + selector = PodGenerator.build_selector_for_k8s_executor_pod( + dag_id=ti.dag_id, + task_id=ti.task_id, + try_number=ti.try_number, + map_index=ti.map_index, + run_id=ti.run_id, + airflow_worker=ti.queued_by_job_id, + ) + namespace = self._get_pod_namespace(ti) + pod_list = self.kube_client.list_namespaced_pod( + namespace=namespace, + label_selector=selector, + ).items + if not pod_list: + self.log.warning("Cannot find pod for ti %s", ti) + continue + elif len(pod_list) > 1: + self.log.warning("Found multiple pods for ti %s: %s", ti, pod_list) + continue + readable_tis.append(repr(ti)) + self.kube_scheduler.delete_pod(pod_name=pod_list[0].metadata.name, namespace=namespace) + return readable_tis
+ +
[docs] def adopt_launched_task( + self, + kube_client: client.CoreV1Api, + pod: k8s.V1Pod, + tis_to_flush_by_key: dict[TaskInstanceKey, k8s.V1Pod], + ) -> None: + """ + Patch existing pod so that the current KubernetesJobWatcher can monitor it via label selectors. + + :param kube_client: kubernetes client for speaking to kube API + :param pod: V1Pod spec that we will patch with new label + :param tis_to_flush_by_key: TIs that will be flushed if they aren't adopted + """ + if TYPE_CHECKING: + assert self.scheduler_job_id + + self.log.info("attempting to adopt pod %s", pod.metadata.name) + ti_key = annotations_to_key(pod.metadata.annotations) + if ti_key not in tis_to_flush_by_key: + self.log.error("attempting to adopt taskinstance which was not specified by database: %s", ti_key) + return + + new_worker_id_label = self._make_safe_label_value(self.scheduler_job_id) + from kubernetes.client.rest import ApiException + + try: + kube_client.patch_namespaced_pod( + name=pod.metadata.name, + namespace=pod.metadata.namespace, + body={"metadata": {"labels": {"airflow-worker": new_worker_id_label}}}, + ) + except ApiException as e: + self.log.info("Failed to adopt pod %s. Reason: %s", pod.metadata.name, e) + return + + del tis_to_flush_by_key[ti_key] + self.running.add(ti_key)
+ + def _adopt_completed_pods(self, kube_client: client.CoreV1Api) -> None: + """ + Patch completed pods so that the KubernetesJobWatcher can delete them. + + :param kube_client: kubernetes client for speaking to kube API + """ + if TYPE_CHECKING: + assert self.scheduler_job_id + + new_worker_id_label = self._make_safe_label_value(self.scheduler_job_id) + query_kwargs = { + "field_selector": "status.phase=Succeeded", + "label_selector": ( + "kubernetes_executor=True," + f"airflow-worker!={new_worker_id_label},{POD_EXECUTOR_DONE_KEY}!=True" + ), + } + pod_list = self._list_pods(query_kwargs) + for pod in pod_list: + self.log.info("Attempting to adopt pod %s", pod.metadata.name) + from kubernetes.client.rest import ApiException + + try: + kube_client.patch_namespaced_pod( + name=pod.metadata.name, + namespace=pod.metadata.namespace, + body={"metadata": {"labels": {"airflow-worker": new_worker_id_label}}}, + ) + except ApiException as e: + self.log.info("Failed to adopt pod %s. Reason: %s", pod.metadata.name, e) + ti_id = annotations_to_key(pod.metadata.annotations) + self.running.add(ti_id) + + def _flush_task_queue(self) -> None: + if TYPE_CHECKING: + assert self.task_queue + + self.log.debug("Executor shutting down, task_queue approximate size=%d", self.task_queue.qsize()) + with contextlib.suppress(Empty): + while True: + task = self.task_queue.get_nowait() + # This is a new task to run thus ok to ignore. + self.log.warning("Executor shutting down, will NOT run task=%s", task) + self.task_queue.task_done() + + def _flush_result_queue(self) -> None: + if TYPE_CHECKING: + assert self.result_queue + + self.log.debug("Executor shutting down, result_queue approximate size=%d", self.result_queue.qsize()) + with contextlib.suppress(Empty): + while True: + results = self.result_queue.get_nowait() + self.log.warning("Executor shutting down, flushing results=%s", results) + try: + key, state, pod_name, namespace, resource_version = results + self.log.info( + "Changing state of %s to %s : resource_version=%d", results, state, resource_version + ) + try: + self._change_state(key, state, pod_name, namespace) + except Exception as e: + self.log.exception( + "Ignoring exception: %s when attempting to change state of %s to %s.", + e, + results, + state, + ) + finally: + self.result_queue.task_done() + +
[docs] def end(self) -> None: + """Shut down the executor.""" + if TYPE_CHECKING: + assert self.task_queue + assert self.result_queue + assert self.kube_scheduler + + self.log.info("Shutting down Kubernetes executor") + try: + self.log.debug("Flushing task_queue...") + self._flush_task_queue() + self.log.debug("Flushing result_queue...") + self._flush_result_queue() + # Both queues should be empty... + self.task_queue.join() + self.result_queue.join() + except ConnectionResetError: + self.log.exception("Connection Reset error while flushing task_queue and result_queue.") + if self.kube_scheduler: + self.kube_scheduler.terminate() + self._manager.shutdown()
+ +
[docs] def terminate(self): + """Terminate the executor is not doing anything."""
+ + @staticmethod +
[docs] def get_cli_commands() -> list[GroupCommand]: + return [ + GroupCommand( + name="kubernetes", + help="Tools to help run the KubernetesExecutor", + subcommands=KUBERNETES_COMMANDS, + ) + ]
+ + +def _get_parser() -> argparse.ArgumentParser: + """ + Generate documentation; used by Sphinx. + + :meta private: + """ + return KubernetesExecutor._get_parser() +
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_types.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_types.html new file mode 100644 index 00000000000..31e61270979 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_types.html @@ -0,0 +1,898 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, Union
+
+
[docs]ADOPTED = "adopted"
+if TYPE_CHECKING: + from airflow.executors.base_executor import CommandType + from airflow.models.taskinstance import TaskInstanceKey + from airflow.utils.state import TaskInstanceState + + # TaskInstance key, command, configuration, pod_template_file +
[docs] KubernetesJobType = Tuple[TaskInstanceKey, CommandType, Any, Optional[str]]
+ + # key, pod state, pod_name, namespace, resource_version + KubernetesResultsType = Tuple[TaskInstanceKey, Optional[Union[TaskInstanceState, str]], str, str, str] + + # pod_name, namespace, pod state, annotations, resource_version + KubernetesWatchType = Tuple[str, str, Optional[Union[TaskInstanceState, str]], Dict[str, str], str] + +
[docs]ALL_NAMESPACES = "ALL_NAMESPACES"
+
[docs]POD_EXECUTOR_DONE_KEY = "airflow_executor_done"
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_utils.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_utils.html new file mode 100644 index 00000000000..b0ec052c734 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_utils.html @@ -0,0 +1,1401 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import contextlib
+import json
+import multiprocessing
+import time
+from queue import Empty, Queue
+from typing import TYPE_CHECKING, Any, Generic, TypeVar
+
+from kubernetes import client, watch
+from kubernetes.client.rest import ApiException
+from urllib3.exceptions import ReadTimeoutError
+
+from airflow.exceptions import AirflowException
+from airflow.providers.cncf.kubernetes.kube_client import get_kube_client
+from airflow.providers.cncf.kubernetes.kubernetes_helper_functions import (
+    annotations_for_logging_task_metadata,
+    annotations_to_key,
+    create_pod_id,
+)
+from airflow.providers.cncf.kubernetes.pod_generator import PodGenerator
+from airflow.utils.log.logging_mixin import LoggingMixin
+from airflow.utils.state import TaskInstanceState
+
+try:
+    from airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types import (
+        ADOPTED,
+        ALL_NAMESPACES,
+        POD_EXECUTOR_DONE_KEY,
+    )
+except ImportError:
+    # avoid failing import when Airflow pre 2.7 is installed
+    from airflow.kubernetes.kubernetes_executor_types import (  # type: ignore[no-redef]
+        ALL_NAMESPACES,
+        POD_EXECUTOR_DONE_KEY,
+    )
+
+if TYPE_CHECKING:
+    from kubernetes.client import Configuration, models as k8s
+
+    from airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types import (
+        KubernetesJobType,
+        KubernetesResultsType,
+        KubernetesWatchType,
+    )
+
+# Singleton here is duplicated version of airflow.utils.singleton.Singleton until
+# min-airflow version is 2.7.0 for the provider. then it can be imported from airflow.utils.singleton.
+
+
[docs]T = TypeVar("T")
+ + +
[docs]class Singleton(type, Generic[T]): + """Metaclass that allows to implement singleton pattern.""" + + _instances: dict[Singleton[T], T] = {} + +
[docs] def __call__(cls: Singleton[T], *args, **kwargs) -> T: + if cls not in cls._instances: + cls._instances[cls] = super().__call__(*args, **kwargs) + return cls._instances[cls]
+ + +
[docs]class ResourceVersion(metaclass=Singleton): + """Singleton for tracking resourceVersion from Kubernetes.""" + +
[docs] resource_version: dict[str, str] = {}
+ + +
[docs]class KubernetesJobWatcher(multiprocessing.Process, LoggingMixin): + """Watches for Kubernetes jobs.""" + + def __init__( + self, + namespace: str, + watcher_queue: Queue[KubernetesWatchType], + resource_version: str | None, + scheduler_job_id: str, + kube_config: Configuration, + ): + super().__init__() + self.namespace = namespace + self.scheduler_job_id = scheduler_job_id + self.watcher_queue = watcher_queue + self.resource_version = resource_version + self.kube_config = kube_config + +
[docs] def run(self) -> None: + """Perform watching.""" + if TYPE_CHECKING: + assert self.scheduler_job_id + + kube_client: client.CoreV1Api = get_kube_client() + while True: + try: + self.resource_version = self._run( + kube_client, self.resource_version, self.scheduler_job_id, self.kube_config + ) + except ReadTimeoutError: + self.log.warning( + "There was a timeout error accessing the Kube API. Retrying request.", exc_info=True + ) + time.sleep(1) + except Exception: + self.log.exception("Unknown error in KubernetesJobWatcher. Failing") + self.resource_version = "0" + ResourceVersion().resource_version[self.namespace] = "0" + raise + else: + self.log.warning( + "Watch died gracefully, starting back up with: last resource_version: %s", + self.resource_version, + )
+ + def _pod_events(self, kube_client: client.CoreV1Api, query_kwargs: dict): + watcher = watch.Watch() + try: + if self.namespace == ALL_NAMESPACES: + return watcher.stream(kube_client.list_pod_for_all_namespaces, **query_kwargs) + else: + return watcher.stream(kube_client.list_namespaced_pod, self.namespace, **query_kwargs) + except ApiException as e: + if str(e.status) == "410": # Resource version is too old + if self.namespace == ALL_NAMESPACES: + pods = kube_client.list_pod_for_all_namespaces(watch=False) + else: + pods = kube_client.list_namespaced_pod(namespace=self.namespace, watch=False) + resource_version = pods.metadata.resource_version + query_kwargs["resource_version"] = resource_version + return self._pod_events(kube_client=kube_client, query_kwargs=query_kwargs) + else: + raise + + def _run( + self, + kube_client: client.CoreV1Api, + resource_version: str | None, + scheduler_job_id: str, + kube_config: Any, + ) -> str | None: + self.log.info("Event: and now my watch begins starting at resource_version: %s", resource_version) + + kwargs = {"label_selector": f"airflow-worker={scheduler_job_id}"} + if resource_version: + kwargs["resource_version"] = resource_version + if kube_config.kube_client_request_args: + for key, value in kube_config.kube_client_request_args.items(): + kwargs[key] = value + + last_resource_version: str | None = None + + for event in self._pod_events(kube_client=kube_client, query_kwargs=kwargs): + task = event["object"] + self.log.debug("Event: %s had an event of type %s", task.metadata.name, event["type"]) + if event["type"] == "ERROR": + return self.process_error(event) + annotations = task.metadata.annotations + task_instance_related_annotations = { + "dag_id": annotations["dag_id"], + "task_id": annotations["task_id"], + "execution_date": annotations.get("execution_date"), + "run_id": annotations.get("run_id"), + "try_number": annotations["try_number"], + } + map_index = annotations.get("map_index") + if map_index is not None: + task_instance_related_annotations["map_index"] = map_index + + self.process_status( + pod_name=task.metadata.name, + namespace=task.metadata.namespace, + status=task.status.phase, + annotations=task_instance_related_annotations, + resource_version=task.metadata.resource_version, + event=event, + ) + last_resource_version = task.metadata.resource_version + + return last_resource_version + +
[docs] def process_error(self, event: Any) -> str: + """Process error response.""" + self.log.error("Encountered Error response from k8s list namespaced pod stream => %s", event) + raw_object = event["raw_object"] + if raw_object["code"] == 410: + self.log.info( + "Kubernetes resource version is too old, must reset to 0 => %s", (raw_object["message"],) + ) + # Return resource version 0 + return "0" + raise AirflowException( + f"Kubernetes failure for {raw_object['reason']} with code {raw_object['code']} and message: " + f"{raw_object['message']}" + )
+ +
[docs] def process_status( + self, + pod_name: str, + namespace: str, + status: str, + annotations: dict[str, str], + resource_version: str, + event: Any, + ) -> None: + pod = event["object"] + annotations_string = annotations_for_logging_task_metadata(annotations) + """Process status response.""" + if event["type"] == "DELETED" and not pod.metadata.deletion_timestamp: + # This will happen only when the task pods are adopted by another executor. + # So, there is no change in the pod state. + # However, need to free the executor slot from the current executor. + self.log.info("Event: pod %s adopted, annotations: %s", pod_name, annotations_string) + self.watcher_queue.put((pod_name, namespace, ADOPTED, annotations, resource_version)) + elif status == "Pending": + # deletion_timestamp is set by kube server when a graceful deletion is requested. + # since kube server have received request to delete pod set TI state failed + if event["type"] == "DELETED" and pod.metadata.deletion_timestamp: + self.log.info("Event: Failed to start pod %s, annotations: %s", pod_name, annotations_string) + self.watcher_queue.put( + (pod_name, namespace, TaskInstanceState.FAILED, annotations, resource_version) + ) + elif ( + self.kube_config.worker_pod_pending_fatal_container_state_reasons + and "status" in event["raw_object"] + ): + self.log.info("Event: %s Pending, annotations: %s", pod_name, annotations_string) + # Init containers and base container statuses to check. + # Skipping the other containers statuses check. + container_statuses_to_check = [] + if "initContainerStatuses" in event["raw_object"]["status"]: + container_statuses_to_check.extend(event["raw_object"]["status"]["initContainerStatuses"]) + if "containerStatuses" in event["raw_object"]["status"]: + container_statuses_to_check.append(event["raw_object"]["status"]["containerStatuses"][0]) + for container_status in container_statuses_to_check: + container_status_state = container_status["state"] + if "waiting" in container_status_state: + if ( + container_status_state["waiting"]["reason"] + in self.kube_config.worker_pod_pending_fatal_container_state_reasons + ): + if ( + container_status_state["waiting"]["reason"] == "ErrImagePull" + and container_status_state["waiting"]["message"] == "pull QPS exceeded" + ): + continue + self.watcher_queue.put( + (pod_name, namespace, TaskInstanceState.FAILED, annotations, resource_version) + ) + break + else: + self.log.debug("Event: %s Pending, annotations: %s", pod_name, annotations_string) + elif status == "Failed": + self.log.error("Event: %s Failed, annotations: %s", pod_name, annotations_string) + self.watcher_queue.put( + (pod_name, namespace, TaskInstanceState.FAILED, annotations, resource_version) + ) + elif status == "Succeeded": + # We get multiple events once the pod hits a terminal state, and we only want to + # send it along to the scheduler once. + # If our event type is DELETED, we have the POD_EXECUTOR_DONE_KEY, or the pod has + # a deletion timestamp, we've already seen the initial Succeeded event and sent it + # along to the scheduler. + if ( + event["type"] == "DELETED" + or POD_EXECUTOR_DONE_KEY in pod.metadata.labels + or pod.metadata.deletion_timestamp + ): + self.log.info( + "Skipping event for Succeeded pod %s - event for this pod already sent to executor", + pod_name, + ) + return + self.log.info("Event: %s Succeeded, annotations: %s", pod_name, annotations_string) + self.watcher_queue.put((pod_name, namespace, None, annotations, resource_version)) + elif status == "Running": + # deletion_timestamp is set by kube server when a graceful deletion is requested. + # since kube server have received request to delete pod set TI state failed + if event["type"] == "DELETED" and pod.metadata.deletion_timestamp: + self.log.info( + "Event: Pod %s deleted before it could complete, annotations: %s", + pod_name, + annotations_string, + ) + self.watcher_queue.put( + (pod_name, namespace, TaskInstanceState.FAILED, annotations, resource_version) + ) + else: + self.log.info("Event: %s is Running, annotations: %s", pod_name, annotations_string) + else: + self.log.warning( + "Event: Invalid state: %s on pod: %s in namespace %s with annotations: %s with " + "resource_version: %s", + status, + pod_name, + namespace, + annotations, + resource_version, + )
+ + +
[docs]class AirflowKubernetesScheduler(LoggingMixin): + """Airflow Scheduler for Kubernetes.""" + + def __init__( + self, + kube_config: Any, + result_queue: Queue[KubernetesResultsType], + kube_client: client.CoreV1Api, + scheduler_job_id: str, + ): + super().__init__() + self.log.debug("Creating Kubernetes executor") + self.kube_config = kube_config + self.result_queue = result_queue + self.namespace = self.kube_config.kube_namespace + self.log.debug("Kubernetes using namespace %s", self.namespace) + self.kube_client = kube_client + self._manager = multiprocessing.Manager() + self.watcher_queue = self._manager.Queue() + self.scheduler_job_id = scheduler_job_id + self.kube_watchers = self._make_kube_watchers() + +
[docs] def run_pod_async(self, pod: k8s.V1Pod, **kwargs): + """Run POD asynchronously.""" + sanitized_pod = self.kube_client.api_client.sanitize_for_serialization(pod) + json_pod = json.dumps(sanitized_pod, indent=2) + + self.log.debug("Pod Creation Request: \n%s", json_pod) + try: + resp = self.kube_client.create_namespaced_pod( + body=sanitized_pod, namespace=pod.metadata.namespace, **kwargs + ) + self.log.debug("Pod Creation Response: %s", resp) + except Exception as e: + self.log.exception("Exception when attempting to create Namespaced Pod: %s", json_pod) + raise e + return resp
+ + def _make_kube_watcher(self, namespace) -> KubernetesJobWatcher: + resource_version = ResourceVersion().resource_version.get(namespace, "0") + watcher = KubernetesJobWatcher( + watcher_queue=self.watcher_queue, + namespace=namespace, + resource_version=resource_version, + scheduler_job_id=self.scheduler_job_id, + kube_config=self.kube_config, + ) + watcher.start() + return watcher + + def _make_kube_watchers(self) -> dict[str, KubernetesJobWatcher]: + watchers = {} + if self.kube_config.multi_namespace_mode: + namespaces_to_watch = ( + self.kube_config.multi_namespace_mode_namespace_list + if self.kube_config.multi_namespace_mode_namespace_list + else [ALL_NAMESPACES] + ) + else: + namespaces_to_watch = [self.kube_config.kube_namespace] + + for namespace in namespaces_to_watch: + watchers[namespace] = self._make_kube_watcher(namespace) + return watchers + + def _health_check_kube_watchers(self): + for namespace, kube_watcher in self.kube_watchers.items(): + if kube_watcher.is_alive(): + self.log.debug("KubeJobWatcher for namespace %s alive, continuing", namespace) + else: + self.log.error( + ( + "Error while health checking kube watcher process for namespace %s. " + "Process died for unknown reasons" + ), + namespace, + ) + ResourceVersion().resource_version[namespace] = "0" + self.kube_watchers[namespace] = self._make_kube_watcher(namespace) + +
[docs] def run_next(self, next_job: KubernetesJobType) -> None: + """Receives the next job to run, builds the pod, and creates it.""" + key, command, kube_executor_config, pod_template_file = next_job + + dag_id, task_id, run_id, try_number, map_index = key + + if command[0:3] != ["airflow", "tasks", "run"]: + raise ValueError('The command must start with ["airflow", "tasks", "run"].') + + base_worker_pod = get_base_pod_from_template(pod_template_file, self.kube_config) + + if not base_worker_pod: + raise AirflowException( + f"could not find a valid worker template yaml at {self.kube_config.pod_template_file}" + ) + + pod = PodGenerator.construct_pod( + namespace=self.namespace, + scheduler_job_id=self.scheduler_job_id, + pod_id=create_pod_id(dag_id, task_id), + dag_id=dag_id, + task_id=task_id, + kube_image=self.kube_config.kube_image, + try_number=try_number, + map_index=map_index, + date=None, + run_id=run_id, + args=command, + pod_override_object=kube_executor_config, + base_worker_pod=base_worker_pod, + with_mutation_hook=True, + ) + # Reconcile the pod generated by the Operator and the Pod + # generated by the .cfg file + self.log.info( + "Creating kubernetes pod for job is %s, with pod name %s, annotations: %s", + key, + pod.metadata.name, + annotations_for_logging_task_metadata(pod.metadata.annotations), + ) + self.log.debug("Kubernetes running for command %s", command) + self.log.debug("Kubernetes launching image %s", pod.spec.containers[0].image) + + # the watcher will monitor pods, so we do not block. + self.run_pod_async(pod, **self.kube_config.kube_client_request_args) + self.log.debug("Kubernetes Job created!")
+ +
[docs] def delete_pod(self, pod_name: str, namespace: str) -> None: + """Delete Pod from a namespace; does not raise if it does not exist.""" + try: + self.log.debug("Deleting pod %s in namespace %s", pod_name, namespace) + self.kube_client.delete_namespaced_pod( + pod_name, + namespace, + body=client.V1DeleteOptions(**self.kube_config.delete_option_kwargs), + **self.kube_config.kube_client_request_args, + ) + except ApiException as e: + # If the pod is already deleted + if str(e.status) != "404": + raise
+ +
[docs] def patch_pod_executor_done(self, *, pod_name: str, namespace: str): + """Add a "done" annotation to ensure we don't continually adopt pods.""" + self.log.debug("Patching pod %s in namespace %s to mark it as done", pod_name, namespace) + try: + self.kube_client.patch_namespaced_pod( + name=pod_name, + namespace=namespace, + body={"metadata": {"labels": {POD_EXECUTOR_DONE_KEY: "True"}}}, + ) + except ApiException as e: + self.log.info("Failed to patch pod %s with done annotation. Reason: %s", pod_name, e)
+ +
[docs] def sync(self) -> None: + """ + Check the status of all currently running kubernetes jobs. + + If a job is completed, its status is placed in the result queue to be sent back to the scheduler. + """ + self.log.debug("Syncing KubernetesExecutor") + self._health_check_kube_watchers() + with contextlib.suppress(Empty): + while True: + task = self.watcher_queue.get_nowait() + try: + self.log.debug("Processing task %s", task) + self.process_watcher_task(task) + finally: + self.watcher_queue.task_done()
+ +
[docs] def process_watcher_task(self, task: KubernetesWatchType) -> None: + """Process the task by watcher.""" + pod_name, namespace, state, annotations, resource_version = task + self.log.debug( + "Attempting to finish pod; pod_name: %s; state: %s; annotations: %s", + pod_name, + state, + annotations_for_logging_task_metadata(annotations), + ) + key = annotations_to_key(annotations=annotations) + if key: + self.log.debug("finishing job %s - %s (%s)", key, state, pod_name) + self.result_queue.put((key, state, pod_name, namespace, resource_version))
+ + def _flush_watcher_queue(self) -> None: + self.log.debug("Executor shutting down, watcher_queue approx. size=%d", self.watcher_queue.qsize()) + with contextlib.suppress(Empty): + while True: + task = self.watcher_queue.get_nowait() + # Ignoring it since it can only have either FAILED or SUCCEEDED pods + self.log.warning("Executor shutting down, IGNORING watcher task=%s", task) + self.watcher_queue.task_done() + +
[docs] def terminate(self) -> None: + """Terminates the watcher.""" + self.log.debug("Terminating kube_watchers...") + for kube_watcher in self.kube_watchers.values(): + kube_watcher.terminate() + kube_watcher.join() + self.log.debug("kube_watcher=%s", kube_watcher) + self.log.debug("Flushing watcher_queue...") + self._flush_watcher_queue() + # Queue should be empty... + self.watcher_queue.join() + self.log.debug("Shutting down manager...") + self._manager.shutdown()
+ + +
[docs]def get_base_pod_from_template(pod_template_file: str | None, kube_config: Any) -> k8s.V1Pod: + """ + Get base pod from template. + + Reads either the pod_template_file set in the executor_config or the base pod_template_file + set in the airflow.cfg to craft a "base pod" that will be used by the KubernetesExecutor + + :param pod_template_file: absolute path to a pod_template_file.yaml or None + :param kube_config: The KubeConfig class generated by airflow that contains all kube metadata + :return: a V1Pod that can be used as the base pod for k8s tasks + """ + if pod_template_file: + return PodGenerator.deserialize_model_file(pod_template_file) + else: + return PodGenerator.deserialize_model_file(kube_config.pod_template_file)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/executors/local_kubernetes_executor.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/executors/local_kubernetes_executor.html new file mode 100644 index 00000000000..219e5a11236 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/executors/local_kubernetes_executor.html @@ -0,0 +1,1108 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Sequence
+
+from airflow.configuration import conf
+from airflow.providers.cncf.kubernetes.executors.kubernetes_executor import KubernetesExecutor
+from airflow.utils.log.logging_mixin import LoggingMixin
+
+if TYPE_CHECKING:
+    from airflow.callbacks.base_callback_sink import BaseCallbackSink
+    from airflow.callbacks.callback_requests import CallbackRequest
+    from airflow.executors.base_executor import CommandType, EventBufferValueType, QueuedTaskInstanceType
+    from airflow.executors.local_executor import LocalExecutor
+    from airflow.models.taskinstance import SimpleTaskInstance, TaskInstance, TaskInstanceKey
+
+
+
[docs]class LocalKubernetesExecutor(LoggingMixin): + """ + Chooses between LocalExecutor and KubernetesExecutor based on the queue defined on the task. + + When the task's queue is the value of ``kubernetes_queue`` in section ``[local_kubernetes_executor]`` + of the configuration (default value: `kubernetes`), KubernetesExecutor is selected to run the task, + otherwise, LocalExecutor is used. + """ + +
[docs] supports_ad_hoc_ti_run: bool = True
+
[docs] supports_pickling: bool = False
+
[docs] supports_sentry: bool = False
+ +
[docs] is_local: bool = False
+
[docs] is_single_threaded: bool = False
+
[docs] is_production: bool = True
+ +
[docs] serve_logs: bool = True
+
[docs] change_sensor_mode_to_reschedule: bool = False
+ +
[docs] callback_sink: BaseCallbackSink | None = None
+ +
[docs] KUBERNETES_QUEUE = conf.get("local_kubernetes_executor", "kubernetes_queue")
+ + def __init__(self, local_executor: LocalExecutor, kubernetes_executor: KubernetesExecutor): + super().__init__() + self._job_id: str | None = None + self.local_executor = local_executor + self.kubernetes_executor = kubernetes_executor + self.kubernetes_executor.kubernetes_queue = self.KUBERNETES_QUEUE + + @property +
[docs] def queued_tasks(self) -> dict[TaskInstanceKey, QueuedTaskInstanceType]: + """Return queued tasks from local and kubernetes executor.""" + queued_tasks = self.local_executor.queued_tasks.copy() + queued_tasks.update(self.kubernetes_executor.queued_tasks) + + return queued_tasks
+ + @property +
[docs] def running(self) -> set[TaskInstanceKey]: + """Return running tasks from local and kubernetes executor.""" + return self.local_executor.running.union(self.kubernetes_executor.running)
+ + @property +
[docs] def job_id(self) -> str | None: + """ + Inherited attribute from BaseExecutor. + + Since this is not really an executor, but a wrapper of executors + we implemented it as property, so we can have custom setter. + """ + return self._job_id
+ + @job_id.setter + def job_id(self, value: str | None) -> None: + """Expose job ID for SchedulerJob.""" + self._job_id = value + self.kubernetes_executor.job_id = value + self.local_executor.job_id = value + +
[docs] def start(self) -> None: + """Start local and kubernetes executor.""" + self.log.info("Starting local and Kubernetes Executor") + self.local_executor.start() + self.kubernetes_executor.start()
+ + @property +
[docs] def slots_available(self) -> int: + """Number of new tasks this executor instance can accept.""" + return self.local_executor.slots_available
+ +
[docs] def queue_command( + self, + task_instance: TaskInstance, + command: CommandType, + priority: int = 1, + queue: str | None = None, + ) -> None: + """Queues command via local or kubernetes executor.""" + executor = self._router(task_instance) + self.log.debug("Using executor: %s for %s", executor.__class__.__name__, task_instance.key) + executor.queue_command(task_instance, command, priority, queue)
+ +
[docs] def queue_task_instance( + self, + task_instance: TaskInstance, + mark_success: bool = False, + pickle_id: int | None = None, + ignore_all_deps: bool = False, + ignore_depends_on_past: bool = False, + wait_for_past_depends_before_skipping: bool = False, + ignore_task_deps: bool = False, + ignore_ti_state: bool = False, + pool: str | None = None, + cfg_path: str | None = None, + ) -> None: + """Queues task instance via local or kubernetes executor.""" + from airflow.models.taskinstance import SimpleTaskInstance + + executor = self._router(SimpleTaskInstance.from_ti(task_instance)) + self.log.debug( + "Using executor: %s to queue_task_instance for %s", executor.__class__.__name__, task_instance.key + ) + executor.queue_task_instance( + task_instance=task_instance, + mark_success=mark_success, + pickle_id=pickle_id, + ignore_all_deps=ignore_all_deps, + ignore_depends_on_past=ignore_depends_on_past, + wait_for_past_depends_before_skipping=wait_for_past_depends_before_skipping, + ignore_task_deps=ignore_task_deps, + ignore_ti_state=ignore_ti_state, + pool=pool, + cfg_path=cfg_path, + )
+ +
[docs] def get_task_log(self, ti: TaskInstance, try_number: int) -> tuple[list[str], list[str]]: + """Fetch task log from kubernetes executor.""" + if ti.queue == self.kubernetes_executor.kubernetes_queue: + return self.kubernetes_executor.get_task_log(ti=ti, try_number=try_number) + return [], []
+ +
[docs] def has_task(self, task_instance: TaskInstance) -> bool: + """ + Check if a task is either queued or running in either local or kubernetes executor. + + :param task_instance: TaskInstance + :return: True if the task is known to this executor + """ + return self.local_executor.has_task(task_instance) or self.kubernetes_executor.has_task(task_instance)
+ +
[docs] def heartbeat(self) -> None: + """Heartbeat sent to trigger new jobs in local and kubernetes executor.""" + self.local_executor.heartbeat() + self.kubernetes_executor.heartbeat()
+ +
[docs] def get_event_buffer( + self, dag_ids: list[str] | None = None + ) -> dict[TaskInstanceKey, EventBufferValueType]: + """ + Return and flush the event buffer from local and kubernetes executor. + + :param dag_ids: dag_ids to return events for, if None returns all + :return: a dict of events + """ + cleared_events_from_local = self.local_executor.get_event_buffer(dag_ids) + cleared_events_from_kubernetes = self.kubernetes_executor.get_event_buffer(dag_ids) + + return {**cleared_events_from_local, **cleared_events_from_kubernetes}
+ +
[docs] def try_adopt_task_instances(self, tis: Sequence[TaskInstance]) -> Sequence[TaskInstance]: + """ + Try to adopt running task instances that have been abandoned by a SchedulerJob dying. + + Anything that is not adopted will be cleared by the scheduler (and then become eligible for + re-scheduling) + + :return: any TaskInstances that were unable to be adopted + """ + local_tis = [ti for ti in tis if ti.queue != self.KUBERNETES_QUEUE] + kubernetes_tis = [ti for ti in tis if ti.queue == self.KUBERNETES_QUEUE] + return [ + *self.local_executor.try_adopt_task_instances(local_tis), + *self.kubernetes_executor.try_adopt_task_instances(kubernetes_tis), + ]
+ +
[docs] def cleanup_stuck_queued_tasks(self, tis: list[TaskInstance]) -> list[str]: + # LocalExecutor doesn't have a cleanup_stuck_queued_tasks method, so we + # will only run KubernetesExecutor's + kubernetes_tis = [ti for ti in tis if ti.queue == self.KUBERNETES_QUEUE] + return self.kubernetes_executor.cleanup_stuck_queued_tasks(kubernetes_tis)
+ +
[docs] def end(self) -> None: + """End local and kubernetes executor.""" + self.local_executor.end() + self.kubernetes_executor.end()
+ +
[docs] def terminate(self) -> None: + """Terminate local and kubernetes executor.""" + self.local_executor.terminate() + self.kubernetes_executor.terminate()
+ + def _router(self, simple_task_instance: SimpleTaskInstance) -> LocalExecutor | KubernetesExecutor: + """ + Return either local_executor or kubernetes_executor. + + :param simple_task_instance: SimpleTaskInstance + :return: local_executor or kubernetes_executor + """ + if simple_task_instance.queue == self.KUBERNETES_QUEUE: + return self.kubernetes_executor + return self.local_executor + +
[docs] def debug_dump(self) -> None: + """Debug dump; called in response to SIGUSR2 by the scheduler.""" + self.log.info("Dumping LocalExecutor state") + self.local_executor.debug_dump() + self.log.info("Dumping KubernetesExecutor state") + self.kubernetes_executor.debug_dump()
+ +
[docs] def send_callback(self, request: CallbackRequest) -> None: + """ + Send callback for execution. + + :param request: Callback request to be executed. + """ + if not self.callback_sink: + raise ValueError("Callback sink is not ready.") + self.callback_sink.send(request)
+ + @staticmethod +
[docs] def get_cli_commands() -> list: + return KubernetesExecutor.get_cli_commands()
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/hooks/kubernetes.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/hooks/kubernetes.html new file mode 100644 index 00000000000..b527139a94c --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/hooks/kubernetes.html @@ -0,0 +1,1679 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.hooks.kubernetes — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.hooks.kubernetes

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import asyncio
+import contextlib
+import json
+import tempfile
+from functools import cached_property
+from time import sleep
+from typing import TYPE_CHECKING, Any, Generator
+
+import aiofiles
+from asgiref.sync import sync_to_async
+from kubernetes import client, config, watch
+from kubernetes.config import ConfigException
+from kubernetes_asyncio import client as async_client, config as async_config
+from urllib3.exceptions import HTTPError
+
+from airflow.exceptions import AirflowException, AirflowNotFoundException
+from airflow.hooks.base import BaseHook
+from airflow.models import Connection
+from airflow.providers.cncf.kubernetes.kube_client import _disable_verify_ssl, _enable_tcp_keepalive
+from airflow.providers.cncf.kubernetes.utils.pod_manager import PodOperatorHookProtocol
+from airflow.utils import yaml
+
+if TYPE_CHECKING:
+    from kubernetes.client import V1JobList
+    from kubernetes.client.models import V1Deployment, V1Job, V1Pod
+
+
[docs]LOADING_KUBE_CONFIG_FILE_RESOURCE = "Loading Kubernetes configuration file kube_config from {}..."
+ +
[docs]JOB_FINAL_STATUS_CONDITION_TYPES = { + "Complete", + "Failed", +}
+ +
[docs]JOB_STATUS_CONDITION_TYPES = JOB_FINAL_STATUS_CONDITION_TYPES | {"Suspended"}
+ + +def _load_body_to_dict(body: str) -> dict: + try: + body_dict = yaml.safe_load(body) + except yaml.YAMLError as e: + raise AirflowException(f"Exception when loading resource definition: {e}\n") + return body_dict + + +
[docs]class KubernetesHook(BaseHook, PodOperatorHookProtocol): + """ + Creates Kubernetes API connection. + + - use in cluster configuration by using extra field ``in_cluster`` in connection + - use custom config by providing path to the file using extra field ``kube_config_path`` in connection + - use custom configuration by providing content of kubeconfig file via + extra field ``kube_config`` in connection + - use default config by providing no extras + + This hook check for configuration option in the above order. Once an option is present it will + use this configuration. + + .. seealso:: + For more information about Kubernetes connection: + :doc:`/connections/kubernetes` + + :param conn_id: The :ref:`kubernetes connection <howto/connection:kubernetes>` + to Kubernetes cluster. + :param client_configuration: Optional dictionary of client configuration params. + Passed on to kubernetes client. + :param cluster_context: Optionally specify a context to use (e.g. if you have multiple + in your kubeconfig. + :param config_file: Path to kubeconfig file. + :param in_cluster: Set to ``True`` if running from within a kubernetes cluster. + :param disable_verify_ssl: Set to ``True`` if SSL verification should be disabled. + :param disable_tcp_keepalive: Set to ``True`` if you want to disable keepalive logic. + """ + +
[docs] conn_name_attr = "kubernetes_conn_id"
+
[docs] default_conn_name = "kubernetes_default"
+
[docs] conn_type = "kubernetes"
+
[docs] hook_name = "Kubernetes Cluster Connection"
+ +
[docs] DEFAULT_NAMESPACE = "default"
+ + @classmethod +
[docs] def get_connection_form_widgets(cls) -> dict[str, Any]: + """Return connection widgets to add to connection form.""" + from flask_appbuilder.fieldwidgets import BS3PasswordFieldWidget, BS3TextFieldWidget + from flask_babel import lazy_gettext + from wtforms import BooleanField, PasswordField, StringField + + return { + "in_cluster": BooleanField(lazy_gettext("In cluster configuration")), + "kube_config_path": StringField(lazy_gettext("Kube config path"), widget=BS3TextFieldWidget()), + "kube_config": PasswordField( + lazy_gettext("Kube config (JSON format)"), widget=BS3PasswordFieldWidget() + ), + "namespace": StringField(lazy_gettext("Namespace"), widget=BS3TextFieldWidget()), + "cluster_context": StringField(lazy_gettext("Cluster context"), widget=BS3TextFieldWidget()), + "disable_verify_ssl": BooleanField(lazy_gettext("Disable SSL")), + "disable_tcp_keepalive": BooleanField(lazy_gettext("Disable TCP keepalive")), + "xcom_sidecar_container_image": StringField( + lazy_gettext("XCom sidecar image"), widget=BS3TextFieldWidget() + ), + "xcom_sidecar_container_resources": StringField( + lazy_gettext("XCom sidecar resources (JSON format)"), widget=BS3TextFieldWidget() + ), + }
+ + @classmethod +
[docs] def get_ui_field_behaviour(cls) -> dict[str, Any]: + """Return custom field behaviour.""" + return { + "hidden_fields": ["host", "schema", "login", "password", "port", "extra"], + "relabeling": {}, + }
+ + def __init__( + self, + conn_id: str | None = default_conn_name, + client_configuration: client.Configuration | None = None, + cluster_context: str | None = None, + config_file: str | None = None, + in_cluster: bool | None = None, + disable_verify_ssl: bool | None = None, + disable_tcp_keepalive: bool | None = None, + ) -> None: + super().__init__() + self.conn_id = conn_id + self.client_configuration = client_configuration + self.cluster_context = cluster_context + self.config_file = config_file + self.in_cluster = in_cluster + self.disable_verify_ssl = disable_verify_ssl + self.disable_tcp_keepalive = disable_tcp_keepalive + self._is_in_cluster: bool | None = None + + @staticmethod + def _coalesce_param(*params): + for param in params: + if param is not None: + return param + + @classmethod +
[docs] def get_connection(cls, conn_id: str) -> Connection: + """ + Return requested connection. + + If missing and conn_id is "kubernetes_default", will return empty connection so that hook will + default to cluster-derived credentials. + """ + try: + return super().get_connection(conn_id) + except AirflowNotFoundException: + if conn_id == cls.default_conn_name: + return Connection(conn_id=cls.default_conn_name) + else: + raise
+ + @cached_property +
[docs] def conn_extras(self): + if self.conn_id: + connection = self.get_connection(self.conn_id) + extras = connection.extra_dejson + else: + extras = {} + return extras
+ + def _get_field(self, field_name): + """ + Handle backcompat for extra fields. + + Prior to Airflow 2.3, in order to make use of UI customizations for extra fields, + we needed to store them with the prefix ``extra__kubernetes__``. This method + handles the backcompat, i.e. if the extra dict contains prefixed fields. + """ + if field_name.startswith("extra__"): + raise ValueError( + f"Got prefixed name {field_name}; please remove the 'extra__kubernetes__' prefix " + f"when using this method." + ) + if field_name in self.conn_extras: + return self.conn_extras[field_name] or None + prefixed_name = f"extra__kubernetes__{field_name}" + return self.conn_extras.get(prefixed_name) or None + +
[docs] def get_conn(self) -> client.ApiClient: + """Return kubernetes api session for use with requests.""" + in_cluster = self._coalesce_param(self.in_cluster, self._get_field("in_cluster")) + cluster_context = self._coalesce_param(self.cluster_context, self._get_field("cluster_context")) + kubeconfig_path = self._coalesce_param(self.config_file, self._get_field("kube_config_path")) + kubeconfig = self._get_field("kube_config") + num_selected_configuration = sum(1 for o in [in_cluster, kubeconfig, kubeconfig_path] if o) + + if num_selected_configuration > 1: + raise AirflowException( + "Invalid connection configuration. Options kube_config_path, " + "kube_config, in_cluster are mutually exclusive. " + "You can only use one option at a time." + ) + + disable_verify_ssl = self._coalesce_param( + self.disable_verify_ssl, _get_bool(self._get_field("disable_verify_ssl")) + ) + disable_tcp_keepalive = self._coalesce_param( + self.disable_tcp_keepalive, _get_bool(self._get_field("disable_tcp_keepalive")) + ) + + if disable_verify_ssl is True: + _disable_verify_ssl() + if disable_tcp_keepalive is not True: + _enable_tcp_keepalive() + + if in_cluster: + self.log.debug("loading kube_config from: in_cluster configuration") + self._is_in_cluster = True + config.load_incluster_config() + return client.ApiClient() + + if kubeconfig_path is not None: + self.log.debug("loading kube_config from: %s", kubeconfig_path) + self._is_in_cluster = False + config.load_kube_config( + config_file=kubeconfig_path, + client_configuration=self.client_configuration, + context=cluster_context, + ) + return client.ApiClient() + + if kubeconfig is not None: + with tempfile.NamedTemporaryFile() as temp_config: + self.log.debug("loading kube_config from: connection kube_config") + temp_config.write(kubeconfig.encode()) + temp_config.flush() + self._is_in_cluster = False + config.load_kube_config( + config_file=temp_config.name, + client_configuration=self.client_configuration, + context=cluster_context, + ) + return client.ApiClient() + + return self._get_default_client(cluster_context=cluster_context)
+ + def _get_default_client(self, *, cluster_context: str | None = None) -> client.ApiClient: + # if we get here, then no configuration has been supplied + # we should try in_cluster since that's most likely + # but failing that just load assuming a kubeconfig file + # in the default location + try: + config.load_incluster_config(client_configuration=self.client_configuration) + self._is_in_cluster = True + except ConfigException: + self.log.debug("loading kube_config from: default file") + self._is_in_cluster = False + config.load_kube_config( + client_configuration=self.client_configuration, + context=cluster_context, + ) + return client.ApiClient() + + @property +
[docs] def is_in_cluster(self) -> bool: + """Expose whether the hook is configured with ``load_incluster_config`` or not.""" + if self._is_in_cluster is not None: + return self._is_in_cluster + self.api_client # so we can determine if we are in_cluster or not + if TYPE_CHECKING: + assert self._is_in_cluster is not None + return self._is_in_cluster
+ + @cached_property +
[docs] def api_client(self) -> client.ApiClient: + """Cached Kubernetes API client.""" + return self.get_conn()
+ + @cached_property +
[docs] def core_v1_client(self) -> client.CoreV1Api: + return client.CoreV1Api(api_client=self.api_client)
+ + @cached_property +
[docs] def apps_v1_client(self) -> client.AppsV1Api: + return client.AppsV1Api(api_client=self.api_client)
+ + @cached_property +
[docs] def custom_object_client(self) -> client.CustomObjectsApi: + return client.CustomObjectsApi(api_client=self.api_client)
+ + @cached_property +
[docs] def batch_v1_client(self) -> client.BatchV1Api: + return client.BatchV1Api(api_client=self.api_client)
+ +
[docs] def create_custom_object( + self, group: str, version: str, plural: str, body: str | dict, namespace: str | None = None + ): + """ + Create custom resource definition object in Kubernetes. + + :param group: api group + :param version: api version + :param plural: api plural + :param body: crd object definition + :param namespace: kubernetes namespace + """ + api: client.CustomObjectsApi = self.custom_object_client + + if isinstance(body, str): + body_dict = _load_body_to_dict(body) + else: + body_dict = body + + response = api.create_namespaced_custom_object( + group=group, + version=version, + namespace=namespace or self.get_namespace() or self.DEFAULT_NAMESPACE, + plural=plural, + body=body_dict, + ) + + self.log.debug("Response: %s", response) + return response
+ +
[docs] def get_custom_object( + self, group: str, version: str, plural: str, name: str, namespace: str | None = None + ): + """ + Get custom resource definition object from Kubernetes. + + :param group: api group + :param version: api version + :param plural: api plural + :param name: crd object name + :param namespace: kubernetes namespace + """ + api = client.CustomObjectsApi(self.api_client) + response = api.get_namespaced_custom_object( + group=group, + version=version, + namespace=namespace or self.get_namespace() or self.DEFAULT_NAMESPACE, + plural=plural, + name=name, + ) + return response
+ +
[docs] def delete_custom_object( + self, group: str, version: str, plural: str, name: str, namespace: str | None = None, **kwargs + ): + """ + Delete custom resource definition object from Kubernetes. + + :param group: api group + :param version: api version + :param plural: api plural + :param name: crd object name + :param namespace: kubernetes namespace + """ + api = client.CustomObjectsApi(self.api_client) + return api.delete_namespaced_custom_object( + group=group, + version=version, + namespace=namespace or self.get_namespace() or self.DEFAULT_NAMESPACE, + plural=plural, + name=name, + **kwargs, + )
+ +
[docs] def get_namespace(self) -> str | None: + """Return the namespace that defined in the connection.""" + if self.conn_id: + return self._get_field("namespace") + return None
+ +
[docs] def get_xcom_sidecar_container_image(self): + """Return the xcom sidecar image that defined in the connection.""" + return self._get_field("xcom_sidecar_container_image")
+ +
[docs] def get_xcom_sidecar_container_resources(self): + """Return the xcom sidecar resources that defined in the connection.""" + field = self._get_field("xcom_sidecar_container_resources") + if not field: + return None + return json.loads(field)
+ +
[docs] def get_pod_log_stream( + self, + pod_name: str, + container: str | None = "", + namespace: str | None = None, + ) -> tuple[watch.Watch, Generator[str, None, None]]: + """ + Retrieve a log stream for a container in a kubernetes pod. + + :param pod_name: pod name + :param container: container name + :param namespace: kubernetes namespace + """ + watcher = watch.Watch() + return ( + watcher, + watcher.stream( + self.core_v1_client.read_namespaced_pod_log, + name=pod_name, + container=container, + namespace=namespace or self.get_namespace() or self.DEFAULT_NAMESPACE, + ), + )
+ +
[docs] def get_pod_logs( + self, + pod_name: str, + container: str | None = "", + namespace: str | None = None, + ): + """ + Retrieve a container's log from the specified pod. + + :param pod_name: pod name + :param container: container name + :param namespace: kubernetes namespace + """ + return self.core_v1_client.read_namespaced_pod_log( + name=pod_name, + container=container, + _preload_content=False, + namespace=namespace or self.get_namespace() or self.DEFAULT_NAMESPACE, + )
+ +
[docs] def get_pod(self, name: str, namespace: str) -> V1Pod: + """Read pod object from kubernetes API.""" + return self.core_v1_client.read_namespaced_pod( + name=name, + namespace=namespace, + )
+ +
[docs] def get_namespaced_pod_list( + self, + label_selector: str | None = "", + namespace: str | None = None, + watch: bool = False, + **kwargs, + ): + """ + Retrieve a list of Kind pod which belong default kubernetes namespace. + + :param label_selector: A selector to restrict the list of returned objects by their labels + :param namespace: kubernetes namespace + :param watch: Watch for changes to the described resources and return them as a stream + """ + return self.core_v1_client.list_namespaced_pod( + namespace=namespace or self.get_namespace() or self.DEFAULT_NAMESPACE, + watch=watch, + label_selector=label_selector, + _preload_content=False, + **kwargs, + )
+ +
[docs] def get_deployment_status( + self, + name: str, + namespace: str = "default", + **kwargs, + ) -> V1Deployment: + """Get status of existing Deployment. + + :param name: Name of Deployment to retrieve + :param namespace: Deployment namespace + """ + try: + return self.apps_v1_client.read_namespaced_deployment_status( + name=name, namespace=namespace, pretty=True, **kwargs + ) + except Exception as exc: + raise exc
+ +
[docs] def create_job( + self, + job: V1Job, + **kwargs, + ) -> V1Job: + """ + Run Job. + + :param job: A kubernetes Job object + """ + sanitized_job = self.batch_v1_client.api_client.sanitize_for_serialization(job) + json_job = json.dumps(sanitized_job, indent=2) + + self.log.debug("Job Creation Request: \n%s", json_job) + try: + resp = self.batch_v1_client.create_namespaced_job( + body=sanitized_job, namespace=job.metadata.namespace, **kwargs + ) + self.log.debug("Job Creation Response: %s", resp) + except Exception as e: + self.log.exception( + "Exception when attempting to create Namespaced Job: %s", str(json_job).replace("\n", " ") + ) + raise e + return resp
+ +
[docs] def get_job(self, job_name: str, namespace: str) -> V1Job: + """Get Job of specified name and namespace. + + :param job_name: Name of Job to fetch. + :param namespace: Namespace of the Job. + :return: Job object + """ + return self.batch_v1_client.read_namespaced_job(name=job_name, namespace=namespace, pretty=True)
+ +
[docs] def get_job_status(self, job_name: str, namespace: str) -> V1Job: + """Get job with status of specified name and namespace. + + :param job_name: Name of Job to fetch. + :param namespace: Namespace of the Job. + :return: Job object + """ + return self.batch_v1_client.read_namespaced_job_status( + name=job_name, namespace=namespace, pretty=True + )
+ +
[docs] def wait_until_job_complete(self, job_name: str, namespace: str, job_poll_interval: float = 10) -> V1Job: + """Block job of specified name and namespace until it is complete or failed. + + :param job_name: Name of Job to fetch. + :param namespace: Namespace of the Job. + :param job_poll_interval: Interval in seconds between polling the job status + :return: Job object + """ + while True: + self.log.info("Requesting status for the job '%s' ", job_name) + job: V1Job = self.get_job_status(job_name=job_name, namespace=namespace) + if self.is_job_complete(job=job): + return job + self.log.info("The job '%s' is incomplete. Sleeping for %i sec.", job_name, job_poll_interval) + sleep(job_poll_interval)
+ +
[docs] def list_jobs_all_namespaces(self) -> V1JobList: + """Get list of Jobs from all namespaces. + + :return: V1JobList object + """ + return self.batch_v1_client.list_job_for_all_namespaces(pretty=True)
+ +
[docs] def list_jobs_from_namespace(self, namespace: str) -> V1JobList: + """Get list of Jobs from dedicated namespace. + + :param namespace: Namespace of the Job. + :return: V1JobList object + """ + return self.batch_v1_client.list_namespaced_job(namespace=namespace, pretty=True)
+ +
[docs] def is_job_complete(self, job: V1Job) -> bool: + """Check whether the given job is complete (with success or fail). + + :return: Boolean indicating that the given job is complete. + """ + if status := job.status: + if conditions := status.conditions: + if final_condition_types := list( + c for c in conditions if c.type in JOB_FINAL_STATUS_CONDITION_TYPES and c.status + ): + s = "s" if len(final_condition_types) > 1 else "" + self.log.info( + "The job '%s' state%s: %s", + job.metadata.name, + s, + ", ".join(f"{c.type} at {c.last_transition_time}" for c in final_condition_types), + ) + return True + return False
+ + @staticmethod +
[docs] def is_job_failed(job: V1Job) -> str | bool: + """Check whether the given job is failed. + + :return: Error message if the job is failed, and False otherwise. + """ + if status := job.status: + conditions = status.conditions or [] + if fail_condition := next((c for c in conditions if c.type == "Failed" and c.status), None): + return fail_condition.reason + return False
+ + @staticmethod +
[docs] def is_job_successful(job: V1Job) -> str | bool: + """Check whether the given job is completed successfully.. + + :return: Error message if the job is failed, and False otherwise. + """ + if status := job.status: + conditions = status.conditions or [] + return bool(next((c for c in conditions if c.type == "Complete" and c.status), None)) + return False
+ +
[docs] def patch_namespaced_job(self, job_name: str, namespace: str, body: object) -> V1Job: + """ + Update the specified Job. + + :param job_name: name of the Job + :param namespace: the namespace to run within kubernetes + :param body: json object with parameters for update + """ + return self.batch_v1_client.patch_namespaced_job( + name=job_name, + namespace=namespace, + body=body, + )
+ + +def _get_bool(val) -> bool | None: + """Convert val to bool if can be done with certainty; if we cannot infer intention we return None.""" + if isinstance(val, bool): + return val + elif isinstance(val, str): + if val.strip().lower() == "true": + return True + elif val.strip().lower() == "false": + return False + return None + + +
[docs]class AsyncKubernetesHook(KubernetesHook): + """Hook to use Kubernetes SDK asynchronously.""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._extras: dict | None = None + + async def _load_config(self): + """Return Kubernetes API session for use with requests.""" + in_cluster = self._coalesce_param(self.in_cluster, await self._get_field("in_cluster")) + cluster_context = self._coalesce_param(self.cluster_context, await self._get_field("cluster_context")) + kubeconfig_path = self._coalesce_param(self.config_file, await self._get_field("kube_config_path")) + kubeconfig = await self._get_field("kube_config") + + num_selected_configuration = sum(1 for o in [in_cluster, kubeconfig, kubeconfig_path] if o) + + if num_selected_configuration > 1: + raise AirflowException( + "Invalid connection configuration. Options kube_config_path, " + "kube_config, in_cluster are mutually exclusive. " + "You can only use one option at a time." + ) + + if in_cluster: + self.log.debug(LOADING_KUBE_CONFIG_FILE_RESOURCE.format("within a pod")) + self._is_in_cluster = True + async_config.load_incluster_config() + return async_client.ApiClient() + + if kubeconfig_path: + self.log.debug(LOADING_KUBE_CONFIG_FILE_RESOURCE.format("kube_config")) + self._is_in_cluster = False + await async_config.load_kube_config( + config_file=kubeconfig_path, + client_configuration=self.client_configuration, + context=cluster_context, + ) + return async_client.ApiClient() + + if kubeconfig is not None: + async with aiofiles.tempfile.NamedTemporaryFile() as temp_config: + self.log.debug( + "Reading kubernetes configuration file from connection " + "object and writing temporary config file with its content", + ) + await temp_config.write(kubeconfig.encode()) + await temp_config.flush() + self._is_in_cluster = False + await async_config.load_kube_config( + config_file=temp_config.name, + client_configuration=self.client_configuration, + context=cluster_context, + ) + return async_client.ApiClient() + self.log.debug(LOADING_KUBE_CONFIG_FILE_RESOURCE.format("default configuration file")) + await async_config.load_kube_config( + client_configuration=self.client_configuration, + context=cluster_context, + ) + +
[docs] async def get_conn_extras(self) -> dict: + if self._extras is None: + if self.conn_id: + connection = await sync_to_async(self.get_connection)(self.conn_id) + self._extras = connection.extra_dejson + else: + self._extras = {} + return self._extras
+ + async def _get_field(self, field_name): + if field_name.startswith("extra__"): + raise ValueError( + f"Got prefixed name {field_name}; please remove the 'extra__kubernetes__' prefix " + "when using this method." + ) + extras = await self.get_conn_extras() + if field_name in extras: + return extras.get(field_name) + prefixed_name = f"extra__kubernetes__{field_name}" + return extras.get(prefixed_name) + + @contextlib.asynccontextmanager +
[docs] async def get_conn(self) -> async_client.ApiClient: + kube_client = None + try: + kube_client = await self._load_config() or async_client.ApiClient() + yield kube_client + finally: + if kube_client is not None: + await kube_client.close()
+ +
[docs] async def get_pod(self, name: str, namespace: str) -> V1Pod: + """ + Get pod's object. + + :param name: Name of the pod. + :param namespace: Name of the pod's namespace. + """ + async with self.get_conn() as connection: + v1_api = async_client.CoreV1Api(connection) + pod: V1Pod = await v1_api.read_namespaced_pod( + name=name, + namespace=namespace, + ) + return pod
+ +
[docs] async def delete_pod(self, name: str, namespace: str): + """ + Delete pod's object. + + :param name: Name of the pod. + :param namespace: Name of the pod's namespace. + """ + async with self.get_conn() as connection: + try: + v1_api = async_client.CoreV1Api(connection) + await v1_api.delete_namespaced_pod( + name=name, namespace=namespace, body=client.V1DeleteOptions() + ) + except async_client.ApiException as e: + # If the pod is already deleted + if str(e.status) != "404": + raise
+ +
[docs] async def read_logs(self, name: str, namespace: str): + """ + Read logs inside the pod while starting containers inside. + + All the logs will be outputted with its timestamp to track + the logs after the execution of the pod is completed. The + method is used for async output of the logs only in the pod + failed it execution or the task was cancelled by the user. + + :param name: Name of the pod. + :param namespace: Name of the pod's namespace. + """ + async with self.get_conn() as connection: + try: + v1_api = async_client.CoreV1Api(connection) + logs = await v1_api.read_namespaced_pod_log( + name=name, + namespace=namespace, + follow=False, + timestamps=True, + ) + logs = logs.splitlines() + for line in logs: + self.log.info("Container logs from %s", line) + return logs + except HTTPError: + self.log.exception("There was an error reading the kubernetes API.") + raise
+ +
[docs] async def get_job_status(self, name: str, namespace: str) -> V1Job: + """ + Get job's status object. + + :param name: Name of the pod. + :param namespace: Name of the pod's namespace. + """ + async with self.get_conn() as connection: + v1_api = async_client.BatchV1Api(connection) + job: V1Job = await v1_api.read_namespaced_job_status( + name=name, + namespace=namespace, + ) + return job
+ +
[docs] async def wait_until_job_complete(self, name: str, namespace: str, poll_interval: float = 10) -> V1Job: + """Block job of specified name and namespace until it is complete or failed. + + :param name: Name of Job to fetch. + :param namespace: Namespace of the Job. + :param poll_interval: Interval in seconds between polling the job status + :return: Job object + """ + while True: + self.log.info("Requesting status for the job '%s' ", name) + job: V1Job = await self.get_job_status(name=name, namespace=namespace) + if self.is_job_complete(job=job): + return job + self.log.info("The job '%s' is incomplete. Sleeping for %i sec.", name, poll_interval) + await asyncio.sleep(poll_interval)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/k8s_model.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/k8s_model.html new file mode 100644 index 00000000000..d51c236e278 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/k8s_model.html @@ -0,0 +1,923 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.k8s_model — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.k8s_model

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""Classes for interacting with Kubernetes API."""
+
+from __future__ import annotations
+
+from abc import ABC, abstractmethod
+from functools import reduce
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING:
+    from kubernetes.client import models as k8s
+
+
+
[docs]class K8SModel(ABC): + """ + Airflow Kubernetes models are here for backwards compatibility reasons only. + + Ideally clients should use the kubernetes API + and the process of + + client input -> Airflow k8s models -> k8s models + + can be avoided. All of these models implement the + `attach_to_pod` method so that they integrate with the kubernetes client. + """ + + @abstractmethod +
[docs] def attach_to_pod(self, pod: k8s.V1Pod) -> k8s.V1Pod: + """ + Attaches to pod. + + :param pod: A pod to attach this Kubernetes object to + :return: The pod with the object attached + """
+ + +
[docs]def append_to_pod(pod: k8s.V1Pod, k8s_objects: list[K8SModel] | None): + """ + Attach additional specs to an existing pod object. + + :param pod: A pod to attach a list of Kubernetes objects to + :param k8s_objects: a potential None list of K8SModels + :return: pod with the objects attached if they exist + """ + if not k8s_objects: + return pod + return reduce(lambda p, o: o.attach_to_pod(p), k8s_objects, pod)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/kube_client.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/kube_client.html new file mode 100644 index 00000000000..4a973159a0c --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/kube_client.html @@ -0,0 +1,1008 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.kube_client — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.kube_client

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""Client for kubernetes communication."""
+
+from __future__ import annotations
+
+import logging
+
+import urllib3.util
+
+from airflow.configuration import conf
+
+
[docs]log = logging.getLogger(__name__)
+ +try: + from kubernetes import client, config + from kubernetes.client import Configuration + from kubernetes.client.rest import ApiException + +
[docs] has_kubernetes = True
+ + def _get_default_configuration() -> Configuration: + if hasattr(Configuration, "get_default_copy"): + return Configuration.get_default_copy() + return Configuration() + + def _disable_verify_ssl() -> None: + configuration = _get_default_configuration() + configuration.verify_ssl = False + Configuration.set_default(configuration) + +except ImportError as e: + # We need an exception class to be able to use it in ``except`` elsewhere + # in the code base + ApiException = BaseException + has_kubernetes = False + _import_err = e + + +def _enable_tcp_keepalive() -> None: + """ + Enable TCP keepalive mechanism. + + This prevents urllib3 connection to hang indefinitely when idle connection + is time-outed on services like cloud load balancers or firewalls. + + See https://github.com/apache/airflow/pull/11406 for detailed explanation. + + Please ping @michalmisiewicz or @dimberman in the PR if you want to modify this function. + """ + import socket + + from urllib3.connection import HTTPConnection, HTTPSConnection + + tcp_keep_idle = conf.getint("kubernetes_executor", "tcp_keep_idle") + tcp_keep_intvl = conf.getint("kubernetes_executor", "tcp_keep_intvl") + tcp_keep_cnt = conf.getint("kubernetes_executor", "tcp_keep_cnt") + + socket_options = [(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)] + + if hasattr(socket, "TCP_KEEPIDLE"): + socket_options.append((socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, tcp_keep_idle)) + else: + log.debug("Unable to set TCP_KEEPIDLE on this platform") + + if hasattr(socket, "TCP_KEEPINTVL"): + socket_options.append((socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, tcp_keep_intvl)) + else: + log.debug("Unable to set TCP_KEEPINTVL on this platform") + + if hasattr(socket, "TCP_KEEPCNT"): + socket_options.append((socket.IPPROTO_TCP, socket.TCP_KEEPCNT, tcp_keep_cnt)) + else: + log.debug("Unable to set TCP_KEEPCNT on this platform") + + HTTPSConnection.default_socket_options = HTTPSConnection.default_socket_options + socket_options + HTTPConnection.default_socket_options = HTTPConnection.default_socket_options + socket_options + + +
[docs]def get_kube_client( + in_cluster: bool | None = None, + cluster_context: str | None = None, + config_file: str | None = None, +) -> client.CoreV1Api: + """ + Retrieve Kubernetes client. + + :param in_cluster: whether we are in cluster + :param cluster_context: context of the cluster + :param config_file: configuration file + :return: kubernetes client + """ + if in_cluster is None: + in_cluster = conf.getboolean("kubernetes_executor", "in_cluster") + if not has_kubernetes: + raise _import_err + + if conf.getboolean("kubernetes_executor", "enable_tcp_keepalive"): + _enable_tcp_keepalive() + + configuration = _get_default_configuration() + api_client_retry_configuration = conf.getjson( + "kubernetes_executor", "api_client_retry_configuration", fallback={} + ) + + if not conf.getboolean("kubernetes_executor", "verify_ssl"): + _disable_verify_ssl() + + if isinstance(api_client_retry_configuration, dict): + configuration.retries = urllib3.util.Retry(**api_client_retry_configuration) + else: + raise ValueError("api_client_retry_configuration should be a dictionary") + + if in_cluster: + config.load_incluster_config(client_configuration=configuration) + else: + if cluster_context is None: + cluster_context = conf.get("kubernetes_executor", "cluster_context", fallback=None) + if config_file is None: + config_file = conf.get("kubernetes_executor", "config_file", fallback=None) + config.load_kube_config( + config_file=config_file, context=cluster_context, client_configuration=configuration + ) + + if not conf.getboolean("kubernetes_executor", "verify_ssl"): + configuration.verify_ssl = False + + ssl_ca_cert = conf.get("kubernetes_executor", "ssl_ca_cert") + if ssl_ca_cert: + configuration.ssl_ca_cert = ssl_ca_cert + + api_client = client.ApiClient(configuration=configuration) + return client.CoreV1Api(api_client)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/kube_config.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/kube_config.html new file mode 100644 index 00000000000..e7374b64c96 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/kube_config.html @@ -0,0 +1,964 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.kube_config — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.kube_config

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from airflow.configuration import conf
+from airflow.exceptions import AirflowConfigException
+from airflow.settings import AIRFLOW_HOME
+
+
+
[docs]class KubeConfig: + """Configuration for Kubernetes.""" + +
[docs] core_section = "core"
+
[docs] kubernetes_section = "kubernetes_executor"
+
[docs] logging_section = "logging"
+ + def __init__(self): + configuration_dict = conf.as_dict(display_sensitive=True) + self.core_configuration = configuration_dict[self.core_section] + self.airflow_home = AIRFLOW_HOME + self.dags_folder = conf.get(self.core_section, "dags_folder") + self.parallelism = conf.getint(self.core_section, "parallelism") + self.pod_template_file = conf.get(self.kubernetes_section, "pod_template_file", fallback=None) + + self.delete_worker_pods = conf.getboolean(self.kubernetes_section, "delete_worker_pods") + self.delete_worker_pods_on_failure = conf.getboolean( + self.kubernetes_section, "delete_worker_pods_on_failure" + ) + self.worker_pod_pending_fatal_container_state_reasons = [] + if conf.get(self.kubernetes_section, "worker_pod_pending_fatal_container_state_reasons", fallback=""): + self.worker_pod_pending_fatal_container_state_reasons = conf.get( + self.kubernetes_section, "worker_pod_pending_fatal_container_state_reasons" + ).split(",") + + self.worker_pods_creation_batch_size = conf.getint( + self.kubernetes_section, "worker_pods_creation_batch_size" + ) + self.worker_container_repository = conf.get(self.kubernetes_section, "worker_container_repository") + self.worker_container_tag = conf.get(self.kubernetes_section, "worker_container_tag") + if self.worker_container_repository and self.worker_container_tag: + self.kube_image = f"{self.worker_container_repository}:{self.worker_container_tag}" + else: + self.kube_image = None + + # The Kubernetes Namespace in which the Scheduler and Webserver reside. Note + # that if your + # cluster has RBAC enabled, your scheduler may need service account permissions to + # create, watch, get, and delete pods in this namespace. + self.kube_namespace = conf.get(self.kubernetes_section, "namespace") + self.multi_namespace_mode = conf.getboolean(self.kubernetes_section, "multi_namespace_mode") + if self.multi_namespace_mode and conf.get( + self.kubernetes_section, "multi_namespace_mode_namespace_list" + ): + self.multi_namespace_mode_namespace_list = conf.get( + self.kubernetes_section, "multi_namespace_mode_namespace_list" + ).split(",") + else: + self.multi_namespace_mode_namespace_list = None + # The Kubernetes Namespace in which pods will be created by the executor. Note + # that if your + # cluster has RBAC enabled, your workers may need service account permissions to + # interact with cluster components. + self.executor_namespace = conf.get(self.kubernetes_section, "namespace") + + self.worker_pods_queued_check_interval = conf.getint( + self.kubernetes_section, "worker_pods_queued_check_interval" + ) + + self.kube_client_request_args = conf.getjson( + self.kubernetes_section, "kube_client_request_args", fallback={} + ) + if not isinstance(self.kube_client_request_args, dict): + raise AirflowConfigException( + f"[{self.kubernetes_section}] 'kube_client_request_args' expected a JSON dict, got " + + type(self.kube_client_request_args).__name__ + ) + if self.kube_client_request_args: + if "_request_timeout" in self.kube_client_request_args and isinstance( + self.kube_client_request_args["_request_timeout"], list + ): + self.kube_client_request_args["_request_timeout"] = tuple( + self.kube_client_request_args["_request_timeout"] + ) + self.delete_option_kwargs = conf.getjson(self.kubernetes_section, "delete_option_kwargs", fallback={}) + if not isinstance(self.delete_option_kwargs, dict): + raise AirflowConfigException( + f"[{self.kubernetes_section}] 'delete_option_kwargs' expected a JSON dict, got " + + type(self.delete_option_kwargs).__name__ + )
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/kubernetes_helper_functions.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/kubernetes_helper_functions.html new file mode 100644 index 00000000000..627ea448f81 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/kubernetes_helper_functions.html @@ -0,0 +1,1062 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.kubernetes_helper_functions — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.kubernetes_helper_functions

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import logging
+import secrets
+import string
+import warnings
+from typing import TYPE_CHECKING
+
+import pendulum
+from slugify import slugify
+
+from airflow.compat.functools import cache
+from airflow.configuration import conf
+from airflow.exceptions import AirflowProviderDeprecationWarning
+
+if TYPE_CHECKING:
+    from airflow.models.taskinstancekey import TaskInstanceKey
+
+
[docs]log = logging.getLogger(__name__)
+ +
[docs]alphanum_lower = string.ascii_lowercase + string.digits
+ +
[docs]POD_NAME_MAX_LENGTH = 63 # Matches Linux kernel's HOST_NAME_MAX default value minus 1.
+ + +def rand_str(num): + """Generate random lowercase alphanumeric string of length num. + + :meta private: + """ + return "".join(secrets.choice(alphanum_lower) for _ in range(num)) + + +def add_unique_suffix(*, name: str, rand_len: int = 8, max_len: int = POD_NAME_MAX_LENGTH) -> str: + """Add random string to pod or job name while staying under max length. + + :param name: name of the pod or job + :param rand_len: length of the random string to append + :param max_len: maximum length of the pod name + :meta private: + """ + suffix = "-" + rand_str(rand_len) + return name[: max_len - len(suffix)].strip("-.") + suffix + + +def add_pod_suffix(*, pod_name: str, rand_len: int = 8, max_len: int = POD_NAME_MAX_LENGTH) -> str: + """Add random string to pod name while staying under max length. + + :param pod_name: name of the pod + :param rand_len: length of the random string to append + :param max_len: maximum length of the pod name + :meta private: + """ + warnings.warn( + "This function is deprecated. Please use `add_unique_suffix`.", + AirflowProviderDeprecationWarning, + stacklevel=2, + ) + + suffix = "-" + rand_str(rand_len) + return pod_name[: max_len - len(suffix)].strip("-.") + suffix + + +
[docs]def create_unique_id( + dag_id: str | None = None, + task_id: str | None = None, + *, + max_length: int = POD_NAME_MAX_LENGTH, + unique: bool = True, +) -> str: + """ + Generate unique pod or job ID given a dag_id and / or task_id. + + :param dag_id: DAG ID + :param task_id: Task ID + :param max_length: max number of characters + :param unique: whether a random string suffix should be added + :return: A valid identifier for a kubernetes pod name + """ + if not (dag_id or task_id): + raise ValueError("Must supply either dag_id or task_id.") + name = "" + if dag_id: + name += dag_id + if task_id: + if name: + name += "-" + name += task_id + base_name = slugify(name, lowercase=True)[:max_length].strip(".-") + if unique: + return add_unique_suffix(name=base_name, rand_len=8, max_len=max_length) + else: + return base_name
+ + +
[docs]def create_pod_id( + dag_id: str | None = None, + task_id: str | None = None, + *, + max_length: int = POD_NAME_MAX_LENGTH, + unique: bool = True, +) -> str: + """ + Generate unique pod ID given a dag_id and / or task_id. + + :param dag_id: DAG ID + :param task_id: Task ID + :param max_length: max number of characters + :param unique: whether a random string suffix should be added + :return: A valid identifier for a kubernetes pod name + """ + warnings.warn( + "This function is deprecated. Please use `create_unique_id`.", + AirflowProviderDeprecationWarning, + stacklevel=2, + ) + + if not (dag_id or task_id): + raise ValueError("Must supply either dag_id or task_id.") + name = "" + if dag_id: + name += dag_id + if task_id: + if name: + name += "-" + name += task_id + base_name = slugify(name, lowercase=True)[:max_length].strip(".-") + if unique: + return add_pod_suffix(pod_name=base_name, rand_len=8, max_len=max_length) + else: + return base_name
+ + +
[docs]def annotations_to_key(annotations: dict[str, str]) -> TaskInstanceKey: + """Build a TaskInstanceKey based on pod annotations.""" + log.debug("Creating task key for annotations %s", annotations) + dag_id = annotations["dag_id"] + task_id = annotations["task_id"] + try_number = int(annotations["try_number"]) + annotation_run_id = annotations.get("run_id") + map_index = int(annotations.get("map_index", -1)) + + # Compat: Look up the run_id from the TI table! + from airflow.models.dagrun import DagRun + from airflow.models.taskinstance import TaskInstance, TaskInstanceKey + from airflow.settings import Session + + if not annotation_run_id and "execution_date" in annotations: + execution_date = pendulum.parse(annotations["execution_date"]) + # Do _not_ use create-session, we don't want to expunge + session = Session() + + task_instance_run_id = ( + session.query(TaskInstance.run_id) + .join(TaskInstance.dag_run) + .filter( + TaskInstance.dag_id == dag_id, + TaskInstance.task_id == task_id, + DagRun.execution_date == execution_date, + ) + .scalar() + ) + else: + task_instance_run_id = annotation_run_id + + return TaskInstanceKey( + dag_id=dag_id, + task_id=task_id, + run_id=task_instance_run_id, + try_number=try_number, + map_index=map_index, + )
+ + +@cache +
[docs]def get_logs_task_metadata() -> bool: + return conf.getboolean("kubernetes_executor", "logs_task_metadata")
+ + +
[docs]def annotations_for_logging_task_metadata(annotation_set): + if get_logs_task_metadata(): + annotations_for_logging = annotation_set + else: + annotations_for_logging = "<omitted>" + return annotations_for_logging
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/custom_object_launcher.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/custom_object_launcher.html new file mode 100644 index 00000000000..0827b66e40d --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/custom_object_launcher.html @@ -0,0 +1,1229 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.operators.custom_object_launcher — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.operators.custom_object_launcher

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""Launches Custom object."""
+
+from __future__ import annotations
+
+import time
+from copy import deepcopy
+from datetime import datetime as dt
+from functools import cached_property
+
+import tenacity
+from kubernetes.client import CoreV1Api, CustomObjectsApi, models as k8s
+from kubernetes.client.rest import ApiException
+
+from airflow.exceptions import AirflowException
+from airflow.providers.cncf.kubernetes.resource_convert.configmap import (
+    convert_configmap,
+    convert_configmap_to_volume,
+)
+from airflow.providers.cncf.kubernetes.resource_convert.env_variable import convert_env_vars
+from airflow.providers.cncf.kubernetes.resource_convert.secret import (
+    convert_image_pull_secrets,
+    convert_secret,
+)
+from airflow.providers.cncf.kubernetes.utils.pod_manager import PodManager
+from airflow.utils.log.logging_mixin import LoggingMixin
+
+
+
[docs]def should_retry_start_spark_job(exception: BaseException) -> bool: + """Check if an Exception indicates a transient error and warrants retrying.""" + if isinstance(exception, ApiException): + return str(exception.status) == "409" + return False
+ + +
[docs]class SparkJobSpec: + """Spark job spec.""" + + def __init__(self, **entries): + self.__dict__.update(entries) + self.validate() + self.update_resources() + +
[docs] def validate(self): + if self.spec.get("dynamicAllocation", {}).get("enabled"): + if not all( + [ + self.spec["dynamicAllocation"].get("initialExecutors"), + self.spec["dynamicAllocation"].get("minExecutors"), + self.spec["dynamicAllocation"].get("maxExecutors"), + ] + ): + raise AirflowException("Make sure initial/min/max value for dynamic allocation is passed")
+ +
[docs] def update_resources(self): + if self.spec["driver"].get("container_resources"): + spark_resources = SparkResources( + self.spec["driver"].pop("container_resources"), + self.spec["executor"].pop("container_resources"), + ) + self.spec["driver"].update(spark_resources.resources["driver"]) + self.spec["executor"].update(spark_resources.resources["executor"])
+ + +
[docs]class KubernetesSpec: + """Spark kubernetes spec.""" + + def __init__(self, **entries): + self.__dict__.update(entries) + self.set_attribute() + +
[docs] def set_attribute(self): + self.env_vars = convert_env_vars(self.env_vars) if self.env_vars else [] + self.image_pull_secrets = ( + convert_image_pull_secrets(self.image_pull_secrets) if self.image_pull_secrets else [] + ) + if self.config_map_mounts: + vols, vols_mounts = convert_configmap_to_volume(self.config_map_mounts) + self.volumes.extend(vols) + self.volume_mounts.extend(vols_mounts) + if self.from_env_config_map: + self.env_from.extend([convert_configmap(c_name) for c_name in self.from_env_config_map]) + if self.from_env_secret: + self.env_from.extend([convert_secret(c) for c in self.from_env_secret])
+ + +
[docs]class SparkResources: + """spark resources.""" + + def __init__( + self, + driver: dict | None = None, + executor: dict | None = None, + ): + self.default = { + "gpu": {"name": None, "quantity": 0}, + "cpu": {"request": None, "limit": None}, + "memory": {"request": None, "limit": None}, + } + self.driver = deepcopy(self.default) + self.executor = deepcopy(self.default) + if driver: + self.driver.update(driver) + if executor: + self.executor.update(executor) + self.convert_resources() + + @property +
[docs] def resources(self): + """Return job resources.""" + return {"driver": self.driver_resources, "executor": self.executor_resources}
+ + @property +
[docs] def driver_resources(self): + """Return resources to use.""" + driver = {} + if self.driver["cpu"].get("request"): + driver["cores"] = self.driver["cpu"]["request"] + if self.driver["cpu"].get("limit"): + driver["coreLimit"] = self.driver["cpu"]["limit"] + if self.driver["memory"].get("limit"): + driver["memory"] = self.driver["memory"]["limit"] + if self.driver["gpu"].get("name") and self.driver["gpu"].get("quantity"): + driver["gpu"] = {"name": self.driver["gpu"]["name"], "quantity": self.driver["gpu"]["quantity"]} + return driver
+ + @property +
[docs] def executor_resources(self): + """Return resources to use.""" + executor = {} + if self.executor["cpu"].get("request"): + executor["cores"] = self.executor["cpu"]["request"] + if self.executor["cpu"].get("limit"): + executor["coreLimit"] = self.executor["cpu"]["limit"] + if self.executor["memory"].get("limit"): + executor["memory"] = self.executor["memory"]["limit"] + if self.executor["gpu"].get("name") and self.executor["gpu"].get("quantity"): + executor["gpu"] = { + "name": self.executor["gpu"]["name"], + "quantity": self.executor["gpu"]["quantity"], + } + return executor
+ +
[docs] def convert_resources(self): + if isinstance(self.driver["memory"].get("limit"), str): + if "G" in self.driver["memory"]["limit"] or "Gi" in self.driver["memory"]["limit"]: + self.driver["memory"]["limit"] = float(self.driver["memory"]["limit"].rstrip("Gi G")) * 1024 + elif "m" in self.driver["memory"]["limit"]: + self.driver["memory"]["limit"] = float(self.driver["memory"]["limit"].rstrip("m")) + # Adjusting the memory value as operator adds 40% to the given value + self.driver["memory"]["limit"] = str(int(self.driver["memory"]["limit"] / 1.4)) + "m" + + if isinstance(self.executor["memory"].get("limit"), str): + if "G" in self.executor["memory"]["limit"] or "Gi" in self.executor["memory"]["limit"]: + self.executor["memory"]["limit"] = ( + float(self.executor["memory"]["limit"].rstrip("Gi G")) * 1024 + ) + elif "m" in self.executor["memory"]["limit"]: + self.executor["memory"]["limit"] = float(self.executor["memory"]["limit"].rstrip("m")) + # Adjusting the memory value as operator adds 40% to the given value + self.executor["memory"]["limit"] = str(int(self.executor["memory"]["limit"] / 1.4)) + "m" + + if self.driver["cpu"].get("request"): + self.driver["cpu"]["request"] = int(float(self.driver["cpu"]["request"])) + if self.driver["cpu"].get("limit"): + self.driver["cpu"]["limit"] = str(self.driver["cpu"]["limit"]) + if self.executor["cpu"].get("request"): + self.executor["cpu"]["request"] = int(float(self.executor["cpu"]["request"])) + if self.executor["cpu"].get("limit"): + self.executor["cpu"]["limit"] = str(self.executor["cpu"]["limit"]) + + if self.driver["gpu"].get("quantity"): + self.driver["gpu"]["quantity"] = int(float(self.driver["gpu"]["quantity"])) + if self.executor["gpu"].get("quantity"): + self.executor["gpu"]["quantity"] = int(float(self.executor["gpu"]["quantity"]))
+ + +
[docs]class CustomObjectStatus: + """Status of the PODs.""" + +
[docs] SUBMITTED = "SUBMITTED"
+
[docs] RUNNING = "RUNNING"
+
[docs] FAILED = "FAILED"
+
[docs] SUCCEEDED = "SUCCEEDED"
+ + +
[docs]class CustomObjectLauncher(LoggingMixin): + """Launches PODS.""" + + def __init__( + self, + name: str | None, + namespace: str | None, + kube_client: CoreV1Api, + custom_obj_api: CustomObjectsApi, + template_body: str | None = None, + ): + """ + Create custom object launcher(sparkapplications crd). + + :param kube_client: kubernetes client. + """ + super().__init__() + self.name = name + self.namespace = namespace + self.template_body = template_body + self.body: dict = self.get_body() + self.kind = self.body["kind"] + self.plural = f"{self.kind.lower()}s" + if self.body.get("apiVersion"): + self.api_group, self.api_version = self.body["apiVersion"].split("/") + else: + self.api_group = self.body["apiGroup"] + self.api_version = self.body["version"] + self._client = kube_client + self.custom_obj_api = custom_obj_api + self.spark_obj_spec: dict = {} + self.pod_spec: k8s.V1Pod | None = None + + @cached_property +
[docs] def pod_manager(self) -> PodManager: + return PodManager(kube_client=self._client)
+ +
[docs] def get_body(self): + self.body: dict = SparkJobSpec(**self.template_body["spark"]) + self.body.metadata = {"name": self.name, "namespace": self.namespace} + if self.template_body.get("kubernetes"): + k8s_spec: dict = KubernetesSpec(**self.template_body["kubernetes"]) + self.body.spec["volumes"] = k8s_spec.volumes + if k8s_spec.image_pull_secrets: + self.body.spec["imagePullSecrets"] = k8s_spec.image_pull_secrets + for item in ["driver", "executor"]: + # Env List + self.body.spec[item]["env"] = k8s_spec.env_vars + self.body.spec[item]["envFrom"] = k8s_spec.env_from + # Volumes + self.body.spec[item]["volumeMounts"] = k8s_spec.volume_mounts + # Add affinity + self.body.spec[item]["affinity"] = k8s_spec.affinity + self.body.spec[item]["tolerations"] = k8s_spec.tolerations + self.body.spec[item]["nodeSelector"] = k8s_spec.node_selector + # Labels + self.body.spec[item]["labels"] = self.body.spec["labels"] + + return self.body.__dict__
+ + @tenacity.retry( + stop=tenacity.stop_after_attempt(3), + wait=tenacity.wait_random_exponential(), + reraise=True, + retry=tenacity.retry_if_exception(should_retry_start_spark_job), + ) +
[docs] def start_spark_job(self, image=None, code_path=None, startup_timeout: int = 600): + """ + Launch the pod synchronously and waits for completion. + + :param image: image name + :param code_path: path to the .py file for python and jar file for scala + :param startup_timeout: Timeout for startup of the pod (if pod is pending for too long, fails task) + :return: + """ + try: + if image: + self.body["spec"]["image"] = image + if code_path: + self.body["spec"]["mainApplicationFile"] = code_path + self.log.debug("Spark Job Creation Request Submitted") + self.spark_obj_spec = self.custom_obj_api.create_namespaced_custom_object( + group=self.api_group, + version=self.api_version, + namespace=self.namespace, + plural=self.plural, + body=self.body, + ) + self.log.debug("Spark Job Creation Response: %s", self.spark_obj_spec) + + # Wait for the driver pod to come alive + self.pod_spec = k8s.V1Pod( + metadata=k8s.V1ObjectMeta( + labels=self.spark_obj_spec["spec"]["driver"]["labels"], + name=self.spark_obj_spec["metadata"]["name"] + "-driver", + namespace=self.namespace, + ) + ) + curr_time = dt.now() + while self.spark_job_not_running(self.spark_obj_spec): + self.log.warning( + "Spark job submitted but not yet started. job_id: %s", + self.spark_obj_spec["metadata"]["name"], + ) + self.check_pod_start_failure() + delta = dt.now() - curr_time + if delta.total_seconds() >= startup_timeout: + pod_status = self.pod_manager.read_pod(self.pod_spec).status.container_statuses + raise AirflowException(f"Job took too long to start. pod status: {pod_status}") + time.sleep(10) + except Exception as e: + self.log.exception("Exception when attempting to create spark job") + raise e + + return self.pod_spec, self.spark_obj_spec
+ +
[docs] def spark_job_not_running(self, spark_obj_spec): + """Test if spark_obj_spec has not started.""" + spark_job_info = self.custom_obj_api.get_namespaced_custom_object_status( + group=self.api_group, + version=self.api_version, + namespace=self.namespace, + name=spark_obj_spec["metadata"]["name"], + plural=self.plural, + ) + driver_state = spark_job_info.get("status", {}).get("applicationState", {}).get("state", "SUBMITTED") + if driver_state == CustomObjectStatus.FAILED: + err = spark_job_info.get("status", {}).get("applicationState", {}).get("errorMessage", "N/A") + try: + self.pod_manager.fetch_container_logs( + pod=self.pod_spec, container_name="spark-kubernetes-driver" + ) + except Exception: + pass + raise AirflowException(f"Spark Job Failed. Error stack: {err}") + return driver_state == CustomObjectStatus.SUBMITTED
+ +
[docs] def check_pod_start_failure(self): + try: + waiting_status = ( + self.pod_manager.read_pod(self.pod_spec).status.container_statuses[0].state.waiting + ) + waiting_reason = waiting_status.reason + waiting_message = waiting_status.message + except Exception: + return + if waiting_reason != "ContainerCreating": + raise AirflowException(f"Spark Job Failed. Status: {waiting_reason}, Error: {waiting_message}")
+ +
[docs] def delete_spark_job(self, spark_job_name=None): + """Delete spark job.""" + spark_job_name = spark_job_name or self.spark_obj_spec.get("metadata", {}).get("name") + if not spark_job_name: + self.log.warning("Spark job not found: %s", spark_job_name) + return + try: + self.custom_obj_api.delete_namespaced_custom_object( + group=self.api_group, + version=self.api_version, + namespace=self.namespace, + plural=self.plural, + name=spark_job_name, + ) + except ApiException as e: + # If the pod is already deleted + if str(e.status) != "404": + raise
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/job.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/job.html new file mode 100644 index 00000000000..5b08427d27f --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/job.html @@ -0,0 +1,1386 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.operators.job — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.operators.job

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""Executes a Kubernetes Job."""
+
+from __future__ import annotations
+
+import copy
+import logging
+import os
+from functools import cached_property
+from typing import TYPE_CHECKING, Sequence
+
+from kubernetes.client import BatchV1Api, models as k8s
+from kubernetes.client.api_client import ApiClient
+from kubernetes.client.rest import ApiException
+
+from airflow.configuration import conf
+from airflow.exceptions import AirflowException
+from airflow.models import BaseOperator
+from airflow.providers.cncf.kubernetes.hooks.kubernetes import KubernetesHook
+from airflow.providers.cncf.kubernetes.kubernetes_helper_functions import (
+    add_unique_suffix,
+    create_unique_id,
+)
+from airflow.providers.cncf.kubernetes.operators.pod import KubernetesPodOperator
+from airflow.providers.cncf.kubernetes.pod_generator import PodGenerator, merge_objects
+from airflow.providers.cncf.kubernetes.triggers.job import KubernetesJobTrigger
+from airflow.utils import yaml
+from airflow.utils.context import Context
+
+if TYPE_CHECKING:
+    from airflow.utils.context import Context
+
+
[docs]log = logging.getLogger(__name__)
+ + +
[docs]class KubernetesJobOperator(KubernetesPodOperator): + """ + Executes a Kubernetes Job. + + .. seealso:: + For more information on how to use this operator, take a look at the guide: + :ref:`howto/operator:KubernetesJobOperator` + + .. note:: + If you use `Google Kubernetes Engine <https://cloud.google.com/kubernetes-engine/>`__ + and Airflow is not running in the same cluster, consider using + :class:`~airflow.providers.google.cloud.operators.kubernetes_engine.GKEStartJobOperator`, which + simplifies the authorization process. + + :param job_template_file: path to job template file (templated) + :param full_job_spec: The complete JodSpec + :param backoff_limit: Specifies the number of retries before marking this job failed. Defaults to 6 + :param completion_mode: CompletionMode specifies how Pod completions are tracked. It can be `NonIndexed` (default) or `Indexed`. + :param completions: Specifies the desired number of successfully finished pods the job should be run with. + :param manual_selector: manualSelector controls generation of pod labels and pod selectors. + :param parallelism: Specifies the maximum desired number of pods the job should run at any given time. + :param selector: The selector of this V1JobSpec. + :param suspend: Suspend specifies whether the Job controller should create Pods or not. + :param ttl_seconds_after_finished: ttlSecondsAfterFinished limits the lifetime of a Job that has finished execution (either Complete or Failed). + :param wait_until_job_complete: Whether to wait until started job finished execution (either Complete or + Failed). Default is False. + :param job_poll_interval: Interval in seconds between polling the job status. Default is 10. + Used if the parameter `wait_until_job_complete` set True. + :param deferrable: Run operator in the deferrable mode. Note that the parameter + `wait_until_job_complete` must be set True. + """ + +
[docs] template_fields: Sequence[str] = tuple({"job_template_file"} | set(KubernetesPodOperator.template_fields))
+ + def __init__( + self, + *, + job_template_file: str | None = None, + full_job_spec: k8s.V1Job | None = None, + backoff_limit: int | None = None, + completion_mode: str | None = None, + completions: int | None = None, + manual_selector: bool | None = None, + parallelism: int | None = None, + selector: k8s.V1LabelSelector | None = None, + suspend: bool | None = None, + ttl_seconds_after_finished: int | None = None, + wait_until_job_complete: bool = False, + job_poll_interval: float = 10, + deferrable: bool = conf.getboolean("operators", "default_deferrable", fallback=False), + **kwargs, + ) -> None: + super().__init__(**kwargs) + self.job_template_file = job_template_file + self.full_job_spec = full_job_spec + self.job_request_obj: k8s.V1Job | None = None + self.job: k8s.V1Job | None = None + self.backoff_limit = backoff_limit + self.completion_mode = completion_mode + self.completions = completions + self.manual_selector = manual_selector + self.parallelism = parallelism + self.selector = selector + self.suspend = suspend + self.ttl_seconds_after_finished = ttl_seconds_after_finished + self.wait_until_job_complete = wait_until_job_complete + self.job_poll_interval = job_poll_interval + self.deferrable = deferrable + + @cached_property + def _incluster_namespace(self): + from pathlib import Path + + path = Path("/var/run/secrets/kubernetes.io/serviceaccount/namespace") + return path.exists() and path.read_text() or None + + @cached_property +
[docs] def hook(self) -> KubernetesHook: + hook = KubernetesHook( + conn_id=self.kubernetes_conn_id, + in_cluster=self.in_cluster, + config_file=self.config_file, + cluster_context=self.cluster_context, + ) + return hook
+ + @cached_property +
[docs] def client(self) -> BatchV1Api: + return self.hook.batch_v1_client
+ +
[docs] def create_job(self, job_request_obj: k8s.V1Job) -> k8s.V1Job: + self.log.debug("Starting job:\n%s", yaml.safe_dump(job_request_obj.to_dict())) + self.hook.create_job(job=job_request_obj) + + return job_request_obj
+ +
[docs] def execute(self, context: Context): + if self.deferrable and not self.wait_until_job_complete: + self.log.warning( + "Deferrable mode is available only with parameter `wait_until_job_complete=True`. " + "Please, set it up." + ) + self.job_request_obj = self.build_job_request_obj(context) + self.job = self.create_job( # must set `self.job` for `on_kill` + job_request_obj=self.job_request_obj + ) + + ti = context["ti"] + ti.xcom_push(key="job_name", value=self.job.metadata.name) + ti.xcom_push(key="job_namespace", value=self.job.metadata.namespace) + + if self.wait_until_job_complete and self.deferrable: + self.execute_deferrable() + return + + if self.wait_until_job_complete: + self.job = self.hook.wait_until_job_complete( + job_name=self.job.metadata.name, + namespace=self.job.metadata.namespace, + job_poll_interval=self.job_poll_interval, + ) + + ti.xcom_push(key="job", value=self.job.to_dict()) + if self.wait_until_job_complete: + if error_message := self.hook.is_job_failed(job=self.job): + raise AirflowException( + f"Kubernetes job '{self.job.metadata.name}' is failed with error '{error_message}'" + )
+ +
[docs] def execute_deferrable(self): + self.defer( + trigger=KubernetesJobTrigger( + job_name=self.job.metadata.name, # type: ignore[union-attr] + job_namespace=self.job.metadata.namespace, # type: ignore[union-attr] + kubernetes_conn_id=self.kubernetes_conn_id, + cluster_context=self.cluster_context, + config_file=self.config_file, + in_cluster=self.in_cluster, + poll_interval=self.job_poll_interval, + ), + method_name="execute_complete", + )
+ +
[docs] def execute_complete(self, context: Context, event: dict, **kwargs): + ti = context["ti"] + ti.xcom_push(key="job", value=event["job"]) + if event["status"] == "error": + raise AirflowException(event["message"])
+ + @staticmethod +
[docs] def deserialize_job_template_file(path: str) -> k8s.V1Job: + """ + Generate a Job from a file. + + Unfortunately we need access to the private method + ``_ApiClient__deserialize_model`` from the kubernetes client. + This issue is tracked here: https://github.com/kubernetes-client/python/issues/977. + + :param path: Path to the file + :return: a kubernetes.client.models.V1Job + """ + if os.path.exists(path): + with open(path) as stream: + job = yaml.safe_load(stream) + else: + job = None + log.warning("Template file %s does not exist", path) + + api_client = ApiClient() + return api_client._ApiClient__deserialize_model(job, k8s.V1Job)
+ +
[docs] def on_kill(self) -> None: + if self.job: + job = self.job + kwargs = { + "name": job.metadata.name, + "namespace": job.metadata.namespace, + "job": self.hook.batch_v1_client.api_client.sanitize_for_serialization(self.job), + } + if self.termination_grace_period is not None: + kwargs.update(grace_period_seconds=self.termination_grace_period) + self.client.delete_namespaced_job(**kwargs)
+ +
[docs] def build_job_request_obj(self, context: Context | None = None) -> k8s.V1Job: + """ + Return V1Job object based on job template file, full job spec, and other operator parameters. + + The V1Job attributes are derived (in order of precedence) from operator params, full job spec, job + template file. + """ + self.log.debug("Creating job for KubernetesJobOperator task %s", self.task_id) + if self.job_template_file: + self.log.debug("Job template file found, will parse for base job") + job_template = self.deserialize_job_template_file(self.job_template_file) + if self.full_job_spec: + job_template = self.reconcile_jobs(job_template, self.full_job_spec) + elif self.full_job_spec: + job_template = self.full_job_spec + else: + job_template = k8s.V1Job(metadata=k8s.V1ObjectMeta()) + + pod_template = super().build_pod_request_obj(context) + pod_template_spec = k8s.V1PodTemplateSpec( + metadata=pod_template.metadata, + spec=pod_template.spec, + ) + + job = k8s.V1Job( + api_version="batch/v1", + kind="Job", + metadata=k8s.V1ObjectMeta( + namespace=self.namespace, + labels=self.labels, + name=self.name, + annotations=self.annotations, + ), + spec=k8s.V1JobSpec( + active_deadline_seconds=self.active_deadline_seconds, + backoff_limit=self.backoff_limit, + completion_mode=self.completion_mode, + completions=self.completions, + manual_selector=self.manual_selector, + parallelism=self.parallelism, + selector=self.selector, + suspend=self.suspend, + template=pod_template_spec, + ttl_seconds_after_finished=self.ttl_seconds_after_finished, + ), + ) + + job = self.reconcile_jobs(job_template, job) + + if not job.metadata.name: + job.metadata.name = create_unique_id( + task_id=self.task_id, unique=self.random_name_suffix, max_length=80 + ) + elif self.random_name_suffix: + # user has supplied job name, we're just adding suffix + job.metadata.name = add_unique_suffix(name=job.metadata.name) + + job.metadata.name = f"job-{job.metadata.name}" + + if not job.metadata.namespace: + hook_namespace = self.hook.get_namespace() + job_namespace = self.namespace or hook_namespace or self._incluster_namespace or "default" + job.metadata.namespace = job_namespace + + self.log.info("Building job %s ", job.metadata.name) + + return job
+ + @staticmethod +
[docs] def reconcile_jobs(base_job: k8s.V1Job, client_job: k8s.V1Job | None) -> k8s.V1Job: + """ + Merge Kubernetes Job objects. + + :param base_job: has the base attributes which are overwritten if they exist + in the client job and remain if they do not exist in the client_job + :param client_job: the job that the client wants to create. + :return: the merged jobs + + This can't be done recursively as certain fields are overwritten and some are concatenated. + """ + if client_job is None: + return base_job + + client_job_cp = copy.deepcopy(client_job) + client_job_cp.spec = KubernetesJobOperator.reconcile_job_specs(base_job.spec, client_job_cp.spec) + client_job_cp.metadata = PodGenerator.reconcile_metadata(base_job.metadata, client_job_cp.metadata) + client_job_cp = merge_objects(base_job, client_job_cp) + + return client_job_cp
+ + @staticmethod +
[docs] def reconcile_job_specs( + base_spec: k8s.V1JobSpec | None, client_spec: k8s.V1JobSpec | None + ) -> k8s.V1JobSpec | None: + """ + Merge Kubernetes JobSpec objects. + + :param base_spec: has the base attributes which are overwritten if they exist + in the client_spec and remain if they do not exist in the client_spec + :param client_spec: the spec that the client wants to create. + :return: the merged specs + """ + if base_spec and not client_spec: + return base_spec + if not base_spec and client_spec: + return client_spec + elif client_spec and base_spec: + client_spec.template.spec = PodGenerator.reconcile_specs( + base_spec.template.spec, client_spec.template.spec + ) + client_spec.template.metadata = PodGenerator.reconcile_metadata( + base_spec.template.metadata, client_spec.template.metadata + ) + return merge_objects(base_spec, client_spec) + + return None
+ + +
[docs]class KubernetesDeleteJobOperator(BaseOperator): + """ + Delete a Kubernetes Job. + + .. seealso:: + For more information on how to use this operator, take a look at the guide: + :ref:`howto/operator:KubernetesDeleteJobOperator` + + :param name: name of the Job. + :param namespace: the namespace to run within kubernetes. + :param kubernetes_conn_id: The :ref:`kubernetes connection id <howto/connection:kubernetes>` + for the Kubernetes cluster. + :param config_file: The path to the Kubernetes config file. (templated) + If not specified, default value is ``~/.kube/config`` + :param in_cluster: run kubernetes client with in_cluster configuration. + :param cluster_context: context that points to kubernetes cluster. + Ignored when in_cluster is True. If None, current-context is used. (templated) + :param delete_on_status: Condition for performing delete operation depending on the job status. Values: + ``None`` - delete the job regardless of its status, "Complete" - delete only successfully completed + jobs, "Failed" - delete only failed jobs. (default: ``None``) + :param wait_for_completion: Whether to wait for the job to complete. (default: ``False``) + :param poll_interval: Interval in seconds between polling the job status. Used when the `delete_on_status` + parameter is set. (default: 10.0) + """ + +
[docs] template_fields: Sequence[str] = ( + "config_file", + "name", + "namespace", + "cluster_context", + )
+ + def __init__( + self, + *, + name: str, + namespace: str, + kubernetes_conn_id: str | None = KubernetesHook.default_conn_name, + config_file: str | None = None, + in_cluster: bool | None = None, + cluster_context: str | None = None, + delete_on_status: str | None = None, + wait_for_completion: bool = False, + poll_interval: float = 10.0, + **kwargs, + ) -> None: + super().__init__(**kwargs) + self.name = name + self.namespace = namespace + self.kubernetes_conn_id = kubernetes_conn_id + self.config_file = config_file + self.in_cluster = in_cluster + self.cluster_context = cluster_context + self.delete_on_status = delete_on_status + self.wait_for_completion = wait_for_completion + self.poll_interval = poll_interval + + @cached_property +
[docs] def hook(self) -> KubernetesHook: + return KubernetesHook( + conn_id=self.kubernetes_conn_id, + in_cluster=self.in_cluster, + config_file=self.config_file, + cluster_context=self.cluster_context, + )
+ + @cached_property +
[docs] def client(self) -> BatchV1Api: + return self.hook.batch_v1_client
+ +
[docs] def execute(self, context: Context): + try: + if self.delete_on_status not in ("Complete", "Failed", None): + raise AirflowException( + "The `delete_on_status` parameter must be one of 'Complete', 'Failed' or None. " + "The current value is %s", + str(self.delete_on_status), + ) + + if self.wait_for_completion: + job = self.hook.wait_until_job_complete( + job_name=self.name, namespace=self.namespace, job_poll_interval=self.poll_interval + ) + else: + job = self.hook.get_job_status(job_name=self.name, namespace=self.namespace) + + if ( + self.delete_on_status is None + or (self.delete_on_status == "Complete" and self.hook.is_job_successful(job=job)) + or (self.delete_on_status == "Failed" and self.hook.is_job_failed(job=job)) + ): + self.log.info("Deleting kubernetes Job: %s", self.name) + self.client.delete_namespaced_job(name=self.name, namespace=self.namespace) + self.log.info("Kubernetes job was deleted.") + else: + self.log.info( + "Deletion of the job %s was skipped due to settings of on_status=%s", + self.name, + self.delete_on_status, + ) + except ApiException as e: + if e.status == 404: + self.log.info("The Kubernetes job %s does not exist.", self.name) + else: + raise e
+ + +
[docs]class KubernetesPatchJobOperator(BaseOperator): + """ + Update a Kubernetes Job. + + .. seealso:: + For more information on how to use this operator, take a look at the guide: + :ref:`howto/operator:KubernetesPatchJobOperator` + + :param name: name of the Job + :param namespace: the namespace to run within kubernetes + :param body: Job json object with parameters for update + https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#job-v1-batch + e.g. ``{"spec": {"suspend": True}}`` + :param kubernetes_conn_id: The :ref:`kubernetes connection id <howto/connection:kubernetes>` + for the Kubernetes cluster. + :param config_file: The path to the Kubernetes config file. (templated) + If not specified, default value is ``~/.kube/config`` + :param in_cluster: run kubernetes client with in_cluster configuration. + :param cluster_context: context that points to kubernetes cluster. + Ignored when in_cluster is True. If None, current-context is used. (templated) + """ + +
[docs] template_fields: Sequence[str] = ( + "config_file", + "name", + "namespace", + "body", + "cluster_context", + )
+ + def __init__( + self, + *, + name: str, + namespace: str, + body: object, + kubernetes_conn_id: str | None = KubernetesHook.default_conn_name, + config_file: str | None = None, + in_cluster: bool | None = None, + cluster_context: str | None = None, + **kwargs, + ) -> None: + super().__init__(**kwargs) + self.name = name + self.namespace = namespace + self.body = body + self.kubernetes_conn_id = kubernetes_conn_id + self.config_file = config_file + self.in_cluster = in_cluster + self.cluster_context = cluster_context + + @cached_property +
[docs] def hook(self) -> KubernetesHook: + return KubernetesHook( + conn_id=self.kubernetes_conn_id, + in_cluster=self.in_cluster, + config_file=self.config_file, + cluster_context=self.cluster_context, + )
+ +
[docs] def execute(self, context: Context) -> dict: + self.log.info("Updating existing Job: %s", self.name) + job_object = self.hook.patch_namespaced_job( + job_name=self.name, namespace=self.namespace, body=self.body + ) + self.log.info("Job was updated.") + return k8s.V1Job.to_dict(job_object)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/pod.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/pod.html new file mode 100644 index 00000000000..5c61fced667 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/pod.html @@ -0,0 +1,1993 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.operators.pod — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.operators.pod

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""Executes task in a Kubernetes POD."""
+
+from __future__ import annotations
+
+import datetime
+import json
+import logging
+import math
+import re
+import shlex
+import string
+import warnings
+from collections.abc import Container
+from contextlib import AbstractContextManager
+from enum import Enum
+from functools import cached_property
+from typing import TYPE_CHECKING, Any, Callable, Iterable, Sequence
+
+import kubernetes
+from deprecated import deprecated
+from kubernetes.client import CoreV1Api, V1Pod, models as k8s
+from kubernetes.stream import stream
+from urllib3.exceptions import HTTPError
+
+from airflow.configuration import conf
+from airflow.exceptions import (
+    AirflowException,
+    AirflowProviderDeprecationWarning,
+    AirflowSkipException,
+    TaskDeferred,
+)
+from airflow.models import BaseOperator
+from airflow.providers.cncf.kubernetes import pod_generator
+from airflow.providers.cncf.kubernetes.backcompat.backwards_compat_converters import (
+    convert_affinity,
+    convert_configmap,
+    convert_env_vars,
+    convert_image_pull_secrets,
+    convert_pod_runtime_info_env,
+    convert_port,
+    convert_toleration,
+    convert_volume,
+    convert_volume_mount,
+)
+from airflow.providers.cncf.kubernetes.callbacks import ExecutionMode, KubernetesPodOperatorCallback
+from airflow.providers.cncf.kubernetes.hooks.kubernetes import KubernetesHook
+from airflow.providers.cncf.kubernetes.kubernetes_helper_functions import (
+    POD_NAME_MAX_LENGTH,
+    add_unique_suffix,
+    create_unique_id,
+)
+from airflow.providers.cncf.kubernetes.pod_generator import PodGenerator
+from airflow.providers.cncf.kubernetes.triggers.pod import KubernetesPodTrigger
+from airflow.providers.cncf.kubernetes.utils import xcom_sidecar  # type: ignore[attr-defined]
+from airflow.providers.cncf.kubernetes.utils.pod_manager import (
+    EMPTY_XCOM_RESULT,
+    OnFinishAction,
+    PodLaunchFailedException,
+    PodManager,
+    PodNotFoundException,
+    PodOperatorHookProtocol,
+    PodPhase,
+    container_is_succeeded,
+    get_container_termination_message,
+)
+from airflow.settings import pod_mutation_hook
+from airflow.utils import yaml
+from airflow.utils.helpers import prune_dict, validate_key
+from airflow.version import version as airflow_version
+
+if TYPE_CHECKING:
+    import jinja2
+    from pendulum import DateTime
+    from typing_extensions import Literal
+
+    from airflow.providers.cncf.kubernetes.secret import Secret
+    from airflow.utils.context import Context
+
+
[docs]alphanum_lower = string.ascii_lowercase + string.digits
+ +
[docs]KUBE_CONFIG_ENV_VAR = "KUBECONFIG"
+ + +
[docs]class PodEventType(Enum): + """Type of Events emitted by kubernetes pod.""" + +
[docs] WARNING = "Warning"
+
[docs] NORMAL = "Normal"
+ + +
[docs]class PodReattachFailure(AirflowException): + """When we expect to be able to find a pod but cannot."""
+ + +
[docs]class KubernetesPodOperator(BaseOperator): + """ + Execute a task in a Kubernetes Pod. + + .. seealso:: + For more information on how to use this operator, take a look at the guide: + :ref:`howto/operator:KubernetesPodOperator` + + .. note:: + If you use `Google Kubernetes Engine <https://cloud.google.com/kubernetes-engine/>`__ + and Airflow is not running in the same cluster, consider using + :class:`~airflow.providers.google.cloud.operators.kubernetes_engine.GKEStartPodOperator`, which + simplifies the authorization process. + + :param kubernetes_conn_id: The :ref:`kubernetes connection id <howto/connection:kubernetes>` + for the Kubernetes cluster. + :param namespace: the namespace to run within kubernetes. + :param image: Docker image you wish to launch. Defaults to hub.docker.com, + but fully qualified URLS will point to custom repositories. (templated) + :param name: name of the pod in which the task will run, will be used (plus a random + suffix if random_name_suffix is True) to generate a pod id (DNS-1123 subdomain, + containing only [a-z0-9.-]). + :param random_name_suffix: if True, will generate a random suffix. + :param cmds: entrypoint of the container. (templated) + The docker images's entrypoint is used if this is not provided. + :param arguments: arguments of the entrypoint. (templated) + The docker image's CMD is used if this is not provided. + :param ports: ports for the launched pod. + :param volume_mounts: volumeMounts for the launched pod. + :param volumes: volumes for the launched pod. Includes ConfigMaps and PersistentVolumes. + :param env_vars: Environment variables initialized in the container. (templated) + :param env_from: (Optional) List of sources to populate environment variables in the container. + :param secrets: Kubernetes secrets to inject in the container. + They can be exposed as environment vars or files in a volume. + :param in_cluster: run kubernetes client with in_cluster configuration. + :param cluster_context: context that points to kubernetes cluster. + Ignored when in_cluster is True. If None, current-context is used. (templated) + :param reattach_on_restart: if the worker dies while the pod is running, reattach and monitor + during the next try. If False, always create a new pod for each try. + :param labels: labels to apply to the Pod. (templated) + :param startup_timeout_seconds: timeout in seconds to startup the pod. + :param startup_check_interval_seconds: interval in seconds to check if the pod has already started + :param get_logs: get the stdout of the base container as logs of the tasks. + :param container_logs: list of containers whose logs will be published to stdout + Takes a sequence of containers, a single container name or True. If True, + all the containers logs are published. Works in conjunction with get_logs param. + The default value is the base container. + :param image_pull_policy: Specify a policy to cache or always pull an image. + :param annotations: non-identifying metadata you can attach to the Pod. + Can be a large range of data, and can include characters + that are not permitted by labels. (templated) + :param container_resources: resources for the launched pod. (templated) + :param affinity: affinity scheduling rules for the launched pod. + :param config_file: The path to the Kubernetes config file. (templated) + If not specified, default value is ``~/.kube/config`` + :param node_selector: A dict containing a group of scheduling rules. + :param image_pull_secrets: Any image pull secrets to be given to the pod. + If more than one secret is required, provide a + comma separated list: secret_a,secret_b + :param service_account_name: Name of the service account + :param hostnetwork: If True enable host networking on the pod. + :param host_aliases: A list of host aliases to apply to the containers in the pod. + :param tolerations: A list of kubernetes tolerations. + :param security_context: security options the pod should run with (PodSecurityContext). + :param container_security_context: security options the container should run with. + :param dnspolicy: dnspolicy for the pod. + :param dns_config: dns configuration (ip addresses, searches, options) for the pod. + :param hostname: hostname for the pod. + :param subdomain: subdomain for the pod. + :param schedulername: Specify a schedulername for the pod + :param full_pod_spec: The complete podSpec + :param init_containers: init container for the launched Pod + :param log_events_on_failure: Log the pod's events if a failure occurs + :param do_xcom_push: If True, the content of the file + /airflow/xcom/return.json in the container will also be pushed to an + XCom when the container completes. + :param pod_template_file: path to pod template file (templated) + :param pod_template_dict: pod template dictionary (templated) + :param priority_class_name: priority class name for the launched Pod + :param pod_runtime_info_envs: (Optional) A list of environment variables, + to be set in the container. + :param termination_grace_period: Termination grace period if task killed in UI, + defaults to kubernetes default + :param configmaps: (Optional) A list of names of config maps from which it collects ConfigMaps + to populate the environment variables with. The contents of the target + ConfigMap's Data field will represent the key-value pairs as environment variables. + Extends env_from. + :param skip_on_exit_code: If task exits with this exit code, leave the task + in ``skipped`` state (default: None). If set to ``None``, any non-zero + exit code will be treated as a failure. + :param base_container_name: The name of the base container in the pod. This container's logs + will appear as part of this task's logs if get_logs is True. Defaults to None. If None, + will consult the class variable BASE_CONTAINER_NAME (which defaults to "base") for the base + container name to use. + :param deferrable: Run operator in the deferrable mode. + :param poll_interval: Polling period in seconds to check for the status. Used only in deferrable mode. + :param log_pod_spec_on_failure: Log the pod's specification if a failure occurs + :param on_finish_action: What to do when the pod reaches its final state, or the execution is interrupted. + If "delete_pod", the pod will be deleted regardless its state; if "delete_succeeded_pod", + only succeeded pod will be deleted. You can set to "keep_pod" to keep the pod. + :param is_delete_operator_pod: What to do when the pod reaches its final + state, or the execution is interrupted. If True (default), delete the + pod; if False, leave the pod. + Deprecated - use `on_finish_action` instead. + :param termination_message_policy: The termination message policy of the base container. + Default value is "File" + :param active_deadline_seconds: The active_deadline_seconds which translates to active_deadline_seconds + in V1PodSpec. + :param callbacks: KubernetesPodOperatorCallback instance contains the callbacks methods on different step + of KubernetesPodOperator. + :param progress_callback: Callback function for receiving k8s container logs. + `progress_callback` is deprecated, please use :param `callbacks` instead. + :param logging_interval: max time in seconds that task should be in deferred state before + resuming to fetch the latest logs. If ``None``, then the task will remain in deferred state until pod + is done, and no logs will be visible until that time. + """ + + # !!! Changes in KubernetesPodOperator's arguments should be also reflected in !!! + # - airflow/decorators/__init__.pyi (by a separate PR) + + # This field can be overloaded at the instance level via base_container_name +
[docs] BASE_CONTAINER_NAME = "base"
+
[docs] ISTIO_CONTAINER_NAME = "istio-proxy"
+
[docs] KILL_ISTIO_PROXY_SUCCESS_MSG = "HTTP/1.1 200"
+
[docs] POD_CHECKED_KEY = "already_checked"
+
[docs] POST_TERMINATION_TIMEOUT = 120
+ +
[docs] template_fields: Sequence[str] = ( + "image", + "cmds", + "annotations", + "arguments", + "env_vars", + "labels", + "config_file", + "pod_template_file", + "pod_template_dict", + "namespace", + "container_resources", + "volumes", + "volume_mounts", + "cluster_context", + "env_from", + )
+
[docs] template_fields_renderers = {"env_vars": "py"}
+ + def __init__( + self, + *, + kubernetes_conn_id: str | None = KubernetesHook.default_conn_name, + namespace: str | None = None, + image: str | None = None, + name: str | None = None, + random_name_suffix: bool = True, + cmds: list[str] | None = None, + arguments: list[str] | None = None, + ports: list[k8s.V1ContainerPort] | None = None, + volume_mounts: list[k8s.V1VolumeMount] | None = None, + volumes: list[k8s.V1Volume] | None = None, + env_vars: list[k8s.V1EnvVar] | dict[str, str] | None = None, + env_from: list[k8s.V1EnvFromSource] | None = None, + secrets: list[Secret] | None = None, + in_cluster: bool | None = None, + cluster_context: str | None = None, + labels: dict | None = None, + reattach_on_restart: bool = True, + startup_timeout_seconds: int = 120, + startup_check_interval_seconds: int = 5, + get_logs: bool = True, + container_logs: Iterable[str] | str | Literal[True] = BASE_CONTAINER_NAME, + image_pull_policy: str | None = None, + annotations: dict | None = None, + container_resources: k8s.V1ResourceRequirements | None = None, + affinity: k8s.V1Affinity | None = None, + config_file: str | None = None, + node_selector: dict | None = None, + image_pull_secrets: list[k8s.V1LocalObjectReference] | None = None, + service_account_name: str | None = None, + hostnetwork: bool = False, + host_aliases: list[k8s.V1HostAlias] | None = None, + tolerations: list[k8s.V1Toleration] | None = None, + security_context: k8s.V1PodSecurityContext | dict | None = None, + container_security_context: k8s.V1SecurityContext | dict | None = None, + dnspolicy: str | None = None, + dns_config: k8s.V1PodDNSConfig | None = None, + hostname: str | None = None, + subdomain: str | None = None, + schedulername: str | None = None, + full_pod_spec: k8s.V1Pod | None = None, + init_containers: list[k8s.V1Container] | None = None, + log_events_on_failure: bool = False, + do_xcom_push: bool = False, + pod_template_file: str | None = None, + pod_template_dict: dict | None = None, + priority_class_name: str | None = None, + pod_runtime_info_envs: list[k8s.V1EnvVar] | None = None, + termination_grace_period: int | None = None, + configmaps: list[str] | None = None, + skip_on_exit_code: int | Container[int] | None = None, + base_container_name: str | None = None, + deferrable: bool = conf.getboolean("operators", "default_deferrable", fallback=False), + poll_interval: float = 2, + log_pod_spec_on_failure: bool = True, + on_finish_action: str = "delete_pod", + is_delete_operator_pod: None | bool = None, + termination_message_policy: str = "File", + active_deadline_seconds: int | None = None, + callbacks: type[KubernetesPodOperatorCallback] | None = None, + progress_callback: Callable[[str], None] | None = None, + logging_interval: int | None = None, + **kwargs, + ) -> None: + super().__init__(**kwargs) + self.kubernetes_conn_id = kubernetes_conn_id + self.do_xcom_push = do_xcom_push + self.image = image + self.namespace = namespace + self.cmds = cmds or [] + self.arguments = arguments or [] + self.labels = labels or {} + self.startup_timeout_seconds = startup_timeout_seconds + self.startup_check_interval_seconds = startup_check_interval_seconds + env_vars = convert_env_vars(env_vars) if env_vars else [] + self.env_vars = env_vars + if pod_runtime_info_envs: + self.env_vars.extend([convert_pod_runtime_info_env(p) for p in pod_runtime_info_envs]) + self.env_from = env_from or [] + if configmaps: + self.env_from.extend([convert_configmap(c) for c in configmaps]) + self.ports = [convert_port(p) for p in ports] if ports else [] + volume_mounts = [convert_volume_mount(v) for v in volume_mounts] if volume_mounts else [] + self.volume_mounts = volume_mounts + volumes = [convert_volume(volume) for volume in volumes] if volumes else [] + self.volumes = volumes + self.secrets = secrets or [] + self.in_cluster = in_cluster + self.cluster_context = cluster_context + self.reattach_on_restart = reattach_on_restart + self.get_logs = get_logs + self.container_logs = container_logs + if self.container_logs == KubernetesPodOperator.BASE_CONTAINER_NAME: + self.container_logs = base_container_name or self.BASE_CONTAINER_NAME + self.image_pull_policy = image_pull_policy + self.node_selector = node_selector or {} + self.annotations = annotations or {} + self.affinity = convert_affinity(affinity) if affinity else {} + self.container_resources = container_resources + self.config_file = config_file + self.image_pull_secrets = convert_image_pull_secrets(image_pull_secrets) if image_pull_secrets else [] + self.service_account_name = service_account_name + self.hostnetwork = hostnetwork + self.host_aliases = host_aliases + self.tolerations = ( + [convert_toleration(toleration) for toleration in tolerations] if tolerations else [] + ) + self.security_context = security_context or {} + self.container_security_context = container_security_context + self.dnspolicy = dnspolicy + self.dns_config = dns_config + self.hostname = hostname + self.subdomain = subdomain + self.schedulername = schedulername + self.full_pod_spec = full_pod_spec + self.init_containers = init_containers or [] + self.log_events_on_failure = log_events_on_failure + self.priority_class_name = priority_class_name + self.pod_template_file = pod_template_file + self.pod_template_dict = pod_template_dict + self.name = self._set_name(name) + self.random_name_suffix = random_name_suffix + self.termination_grace_period = termination_grace_period + self.pod_request_obj: k8s.V1Pod | None = None + self.pod: k8s.V1Pod | None = None + self.skip_on_exit_code = ( + skip_on_exit_code + if isinstance(skip_on_exit_code, Container) + else [skip_on_exit_code] + if skip_on_exit_code is not None + else [] + ) + self.base_container_name = base_container_name or self.BASE_CONTAINER_NAME + self.deferrable = deferrable + self.poll_interval = poll_interval + self.remote_pod: k8s.V1Pod | None = None + self.log_pod_spec_on_failure = log_pod_spec_on_failure + if is_delete_operator_pod is not None: + warnings.warn( + "`is_delete_operator_pod` parameter is deprecated, please use `on_finish_action`", + AirflowProviderDeprecationWarning, + stacklevel=2, + ) + self.on_finish_action = ( + OnFinishAction.DELETE_POD if is_delete_operator_pod else OnFinishAction.KEEP_POD + ) + self.is_delete_operator_pod = is_delete_operator_pod + else: + self.on_finish_action = OnFinishAction(on_finish_action) + self.is_delete_operator_pod = self.on_finish_action == OnFinishAction.DELETE_POD + self.termination_message_policy = termination_message_policy + self.active_deadline_seconds = active_deadline_seconds + self.logging_interval = logging_interval + + self._config_dict: dict | None = None # TODO: remove it when removing convert_config_file_to_dict + self._progress_callback = progress_callback + self.callbacks = callbacks + self._killed: bool = False + + @cached_property + def _incluster_namespace(self): + from pathlib import Path + + path = Path("/var/run/secrets/kubernetes.io/serviceaccount/namespace") + return path.exists() and path.read_text() or None + + def _render_nested_template_fields( + self, + content: Any, + context: Context, + jinja_env: jinja2.Environment, + seen_oids: set, + ) -> None: + if id(content) not in seen_oids: + template_fields: tuple | None + + if isinstance(content, k8s.V1EnvVar): + template_fields = ("value", "name") + elif isinstance(content, k8s.V1ResourceRequirements): + template_fields = ("limits", "requests") + elif isinstance(content, k8s.V1Volume): + template_fields = ("name", "persistent_volume_claim", "config_map") + elif isinstance(content, k8s.V1VolumeMount): + template_fields = ("name", "sub_path") + elif isinstance(content, k8s.V1PersistentVolumeClaimVolumeSource): + template_fields = ("claim_name",) + elif isinstance(content, k8s.V1ConfigMapVolumeSource): + template_fields = ("name",) + elif isinstance(content, k8s.V1EnvFromSource): + template_fields = ("config_map_ref",) + elif isinstance(content, k8s.V1ConfigMapEnvSource): + template_fields = ("name",) + else: + template_fields = None + + if template_fields: + seen_oids.add(id(content)) + self._do_render_template_fields(content, template_fields, context, jinja_env, seen_oids) + return + + super()._render_nested_template_fields(content, context, jinja_env, seen_oids) + + @staticmethod + def _get_ti_pod_labels(context: Context | None = None, include_try_number: bool = True) -> dict[str, str]: + """ + Generate labels for the pod to track the pod in case of Operator crash. + + :param context: task context provided by airflow DAG + :return: dict + """ + if not context: + return {} + + ti = context["ti"] + run_id = context["run_id"] + + labels = { + "dag_id": ti.dag_id, + "task_id": ti.task_id, + "run_id": run_id, + "kubernetes_pod_operator": "True", + } + + map_index = ti.map_index + if map_index >= 0: + labels["map_index"] = map_index + + if include_try_number: + labels.update(try_number=ti.try_number) + # In the case of sub dags this is just useful + if context["dag"].parent_dag: + labels["parent_dag_id"] = context["dag"].parent_dag.dag_id + # Ensure that label is valid for Kube, + # and if not truncate/remove invalid chars and replace with short hash. + for label_id, label in labels.items(): + safe_label = pod_generator.make_safe_label_value(str(label)) + labels[label_id] = safe_label + return labels + + @cached_property +
[docs] def pod_manager(self) -> PodManager: + return PodManager( + kube_client=self.client, callbacks=self.callbacks, progress_callback=self._progress_callback + )
+ + @cached_property +
[docs] def hook(self) -> PodOperatorHookProtocol: + hook = KubernetesHook( + conn_id=self.kubernetes_conn_id, + in_cluster=self.in_cluster, + config_file=self.config_file, + cluster_context=self.cluster_context, + ) + return hook
+ + @cached_property +
[docs] def client(self) -> CoreV1Api: + client = self.hook.core_v1_client + if self.callbacks: + self.callbacks.on_sync_client_creation(client=client) + return client
+ +
[docs] def find_pod(self, namespace: str, context: Context, *, exclude_checked: bool = True) -> k8s.V1Pod | None: + """Return an already-running pod for this task instance if one exists.""" + label_selector = self._build_find_pod_label_selector(context, exclude_checked=exclude_checked) + pod_list = self.client.list_namespaced_pod( + namespace=namespace, + label_selector=label_selector, + ).items + + pod = None + num_pods = len(pod_list) + if num_pods > 1: + raise AirflowException(f"More than one pod running with labels {label_selector}") + elif num_pods == 1: + pod = pod_list[0] + self.log.info("Found matching pod %s with labels %s", pod.metadata.name, pod.metadata.labels) + self.log.info("`try_number` of task_instance: %s", context["ti"].try_number) + self.log.info("`try_number` of pod: %s", pod.metadata.labels["try_number"]) + return pod
+ +
[docs] def get_or_create_pod(self, pod_request_obj: k8s.V1Pod, context: Context) -> k8s.V1Pod: + if self.reattach_on_restart: + pod = self.find_pod(self.namespace or pod_request_obj.metadata.namespace, context=context) + if pod: + return pod + + self.log.debug("Starting pod:\n%s", yaml.safe_dump(pod_request_obj.to_dict())) + self.pod_manager.create_pod(pod=pod_request_obj) + + return pod_request_obj
+ +
[docs] def await_pod_start(self, pod: k8s.V1Pod): + try: + self.pod_manager.await_pod_start( + pod=pod, + startup_timeout=self.startup_timeout_seconds, + startup_check_interval=self.startup_check_interval_seconds, + ) + except PodLaunchFailedException: + if self.log_events_on_failure: + self._read_pod_events(pod, reraise=False) + raise
+ +
[docs] def extract_xcom(self, pod: k8s.V1Pod): + """Retrieve xcom value and kill xcom sidecar container.""" + result = self.pod_manager.extract_xcom(pod) + if isinstance(result, str) and result.rstrip() == EMPTY_XCOM_RESULT: + self.log.info("xcom result file is empty.") + return None + else: + self.log.info("xcom result: \n%s", result) + return json.loads(result)
+ +
[docs] def execute(self, context: Context): + """Based on the deferrable parameter runs the pod asynchronously or synchronously.""" + if self.deferrable: + self.execute_async(context) + else: + return self.execute_sync(context)
+ +
[docs] def execute_sync(self, context: Context): + result = None + try: + if self.pod_request_obj is None: + self.pod_request_obj = self.build_pod_request_obj(context) + if self.pod is None: + self.pod = self.get_or_create_pod( # must set `self.pod` for `on_kill` + pod_request_obj=self.pod_request_obj, + context=context, + ) + # push to xcom now so that if there is an error we still have the values + ti = context["ti"] + ti.xcom_push(key="pod_name", value=self.pod.metadata.name) + ti.xcom_push(key="pod_namespace", value=self.pod.metadata.namespace) + + # get remote pod for use in cleanup methods + self.remote_pod = self.find_pod(self.pod.metadata.namespace, context=context) + if self.callbacks: + self.callbacks.on_pod_creation( + pod=self.remote_pod, client=self.client, mode=ExecutionMode.SYNC + ) + self.await_pod_start(pod=self.pod) + if self.callbacks: + self.callbacks.on_pod_starting( + pod=self.find_pod(self.pod.metadata.namespace, context=context), + client=self.client, + mode=ExecutionMode.SYNC, + ) + + if self.get_logs: + self.pod_manager.fetch_requested_container_logs( + pod=self.pod, + containers=self.container_logs, + follow_logs=True, + ) + if not self.get_logs or ( + self.container_logs is not True and self.base_container_name not in self.container_logs + ): + self.pod_manager.await_container_completion( + pod=self.pod, container_name=self.base_container_name + ) + if self.callbacks: + self.callbacks.on_pod_completion( + pod=self.find_pod(self.pod.metadata.namespace, context=context), + client=self.client, + mode=ExecutionMode.SYNC, + ) + + if self.do_xcom_push: + self.pod_manager.await_xcom_sidecar_container_start(pod=self.pod) + result = self.extract_xcom(pod=self.pod) + istio_enabled = self.is_istio_enabled(self.pod) + self.remote_pod = self.pod_manager.await_pod_completion( + self.pod, istio_enabled, self.base_container_name + ) + finally: + pod_to_clean = self.pod or self.pod_request_obj + self.cleanup( + pod=pod_to_clean, + remote_pod=self.remote_pod, + ) + if self.callbacks: + self.callbacks.on_pod_cleanup(pod=pod_to_clean, client=self.client, mode=ExecutionMode.SYNC) + + if self.do_xcom_push: + return result
+ +
[docs] def execute_async(self, context: Context): + self.pod_request_obj = self.build_pod_request_obj(context) + self.pod = self.get_or_create_pod( # must set `self.pod` for `on_kill` + pod_request_obj=self.pod_request_obj, + context=context, + ) + if self.callbacks: + self.callbacks.on_pod_creation( + pod=self.find_pod(self.pod.metadata.namespace, context=context), + client=self.client, + mode=ExecutionMode.SYNC, + ) + ti = context["ti"] + ti.xcom_push(key="pod_name", value=self.pod.metadata.name) + ti.xcom_push(key="pod_namespace", value=self.pod.metadata.namespace) + + self.invoke_defer_method()
+ +
[docs] def invoke_defer_method(self, last_log_time: DateTime | None = None): + """Redefine triggers which are being used in child classes.""" + trigger_start_time = datetime.datetime.now(tz=datetime.timezone.utc) + self.defer( + trigger=KubernetesPodTrigger( + pod_name=self.pod.metadata.name, # type: ignore[union-attr] + pod_namespace=self.pod.metadata.namespace, # type: ignore[union-attr] + trigger_start_time=trigger_start_time, + kubernetes_conn_id=self.kubernetes_conn_id, + cluster_context=self.cluster_context, + config_file=self.config_file, + in_cluster=self.in_cluster, + poll_interval=self.poll_interval, + get_logs=self.get_logs, + startup_timeout=self.startup_timeout_seconds, + startup_check_interval=self.startup_check_interval_seconds, + base_container_name=self.base_container_name, + on_finish_action=self.on_finish_action.value, + last_log_time=last_log_time, + logging_interval=self.logging_interval, + ), + method_name="trigger_reentry", + )
+ +
[docs] def trigger_reentry(self, context: Context, event: dict[str, Any]) -> Any: + """ + Point of re-entry from trigger. + + If ``logging_interval`` is None, then at this point, the pod should be done, and we'll just fetch + the logs and exit. + + If ``logging_interval`` is not None, it could be that the pod is still running, and we'll just + grab the latest logs and defer back to the trigger again. + """ + self.pod = None + try: + pod_name = event["name"] + pod_namespace = event["namespace"] + + self.pod = self.hook.get_pod(pod_name, pod_namespace) + + if not self.pod: + raise PodNotFoundException("Could not find pod after resuming from deferral") + + if self.callbacks and event["status"] != "running": + self.callbacks.on_operator_resuming( + pod=self.pod, event=event, client=self.client, mode=ExecutionMode.SYNC + ) + + follow = self.logging_interval is None + last_log_time = event.get("last_log_time") + + if event["status"] in ("error", "failed", "timeout"): + # fetch some logs when pod is failed + if self.get_logs: + self.write_logs(self.pod, follow=follow, since_time=last_log_time) + + if self.do_xcom_push: + _ = self.extract_xcom(pod=self.pod) + + message = event.get("stack_trace", event["message"]) + raise AirflowException(message) + + elif event["status"] == "running": + if self.get_logs: + self.log.info("Resuming logs read from time %r", last_log_time) + + pod_log_status = self.pod_manager.fetch_container_logs( + pod=self.pod, + container_name=self.BASE_CONTAINER_NAME, + follow=follow, + since_time=last_log_time, + ) + + if pod_log_status.running: + self.log.info("Container still running; deferring again.") + self.invoke_defer_method(pod_log_status.last_log_time) + else: + self.invoke_defer_method() + + elif event["status"] == "success": + # fetch some logs when pod is executed successfully + if self.get_logs: + self.write_logs(self.pod, follow=follow, since_time=last_log_time) + + if self.do_xcom_push: + xcom_sidecar_output = self.extract_xcom(pod=self.pod) + return xcom_sidecar_output + return + except TaskDeferred: + raise + finally: + self._clean(event)
+ + def _clean(self, event: dict[str, Any]): + if event["status"] == "running": + return + istio_enabled = self.is_istio_enabled(self.pod) + # Skip await_pod_completion when the event is 'timeout' due to the pod can hang + # on the ErrImagePull or ContainerCreating step and it will never complete + if event["status"] != "timeout": + self.pod = self.pod_manager.await_pod_completion( + self.pod, istio_enabled, self.base_container_name + ) + if self.pod is not None: + self.post_complete_action( + pod=self.pod, + remote_pod=self.pod, + ) + + @deprecated(reason="use `trigger_reentry` instead.", category=AirflowProviderDeprecationWarning) +
[docs] def execute_complete(self, context: Context, event: dict, **kwargs): + return self.trigger_reentry(context=context, event=event)
+ +
[docs] def write_logs(self, pod: k8s.V1Pod, follow: bool = False, since_time: DateTime | None = None): + try: + since_seconds = ( + math.ceil((datetime.datetime.now(tz=datetime.timezone.utc) - since_time).total_seconds()) + if since_time + else None + ) + logs = self.pod_manager.read_pod_logs( + pod=pod, + container_name=self.base_container_name, + follow=follow, + since_seconds=since_seconds, + ) + for raw_line in logs: + line = raw_line.decode("utf-8", errors="backslashreplace").rstrip("\n") + if line: + self.log.info("Container logs: %s", line) + except HTTPError as e: + self.log.warning( + "Reading of logs interrupted with error %r; will retry. " + "Set log level to DEBUG for traceback.", + e, + )
+ +
[docs] def post_complete_action(self, *, pod, remote_pod, **kwargs): + """Actions that must be done after operator finishes logic of the deferrable_execution.""" + self.cleanup( + pod=pod, + remote_pod=remote_pod, + ) + if self.callbacks: + self.callbacks.on_pod_cleanup(pod=pod, client=self.client, mode=ExecutionMode.SYNC)
+ +
[docs] def cleanup(self, pod: k8s.V1Pod, remote_pod: k8s.V1Pod): + # Skip cleaning the pod in the following scenarios. + # 1. If a task got marked as failed, "on_kill" method would be called and the pod will be cleaned up + # there. Cleaning it up again will raise an exception (which might cause retry). + # 2. remote pod is null (ex: pod creation failed) + if self._killed or not remote_pod: + return + + istio_enabled = self.is_istio_enabled(remote_pod) + pod_phase = remote_pod.status.phase if hasattr(remote_pod, "status") else None + + # if the pod fails or success, but we don't want to delete it + if pod_phase != PodPhase.SUCCEEDED or self.on_finish_action == OnFinishAction.KEEP_POD: + self.patch_already_checked(remote_pod, reraise=False) + + failed = (pod_phase != PodPhase.SUCCEEDED and not istio_enabled) or ( + istio_enabled and not container_is_succeeded(remote_pod, self.base_container_name) + ) + + if failed: + if self.log_events_on_failure: + self._read_pod_events(pod, reraise=False) + + self.process_pod_deletion(remote_pod, reraise=False) + + if self.skip_on_exit_code: + container_statuses = ( + remote_pod.status.container_statuses if remote_pod and remote_pod.status else None + ) or [] + base_container_status = next( + (x for x in container_statuses if x.name == self.base_container_name), None + ) + exit_code = ( + base_container_status.state.terminated.exit_code + if base_container_status + and base_container_status.state + and base_container_status.state.terminated + else None + ) + if exit_code in self.skip_on_exit_code: + raise AirflowSkipException( + f"Pod {pod and pod.metadata.name} returned exit code {exit_code}. Skipping." + ) + + if failed: + error_message = get_container_termination_message(remote_pod, self.base_container_name) + raise AirflowException( + "\n".join( + filter( + None, + [ + f"Pod {pod and pod.metadata.name} returned a failure.", + error_message if isinstance(error_message, str) else None, + f"remote_pod: {remote_pod}" if self.log_pod_spec_on_failure else None, + ], + ) + ) + )
+ + def _read_pod_events(self, pod, *, reraise=True): + """Will fetch and emit events from pod.""" + with _optionally_suppress(reraise=reraise): + for event in self.pod_manager.read_pod_events(pod).items: + if event.type == PodEventType.NORMAL.value: + self.log.info("Pod Event: %s - %s", event.reason, event.message) + else: + self.log.error("Pod Event: %s - %s", event.reason, event.message) + +
[docs] def is_istio_enabled(self, pod: V1Pod) -> bool: + """Check if istio is enabled for the namespace of the pod by inspecting the namespace labels.""" + if not pod: + return False + + remote_pod = self.pod_manager.read_pod(pod) + + return any(container.name == self.ISTIO_CONTAINER_NAME for container in remote_pod.spec.containers)
+ +
[docs] def kill_istio_sidecar(self, pod: V1Pod) -> None: + command = "/bin/sh -c 'curl -fsI -X POST http://localhost:15020/quitquitquit'" + command_to_container = shlex.split(command) + resp = stream( + self.client.connect_get_namespaced_pod_exec, + name=pod.metadata.name, + namespace=pod.metadata.namespace, + container=self.ISTIO_CONTAINER_NAME, + command=command_to_container, + stderr=True, + stdin=True, + stdout=True, + tty=False, + _preload_content=False, + ) + output = [] + while resp.is_open(): + if resp.peek_stdout(): + output.append(resp.read_stdout()) + + resp.close() + output_str = "".join(output) + self.log.info("Output of curl command to kill istio: %s", output_str) + resp.close() + if self.KILL_ISTIO_PROXY_SUCCESS_MSG not in output_str: + raise AirflowException("Error while deleting istio-proxy sidecar: %s", output_str)
+ +
[docs] def process_pod_deletion(self, pod: k8s.V1Pod, *, reraise=True): + with _optionally_suppress(reraise=reraise): + if pod is not None: + should_delete_pod = ( + (self.on_finish_action == OnFinishAction.DELETE_POD) + or ( + self.on_finish_action == OnFinishAction.DELETE_SUCCEEDED_POD + and pod.status.phase == PodPhase.SUCCEEDED + ) + or ( + self.on_finish_action == OnFinishAction.DELETE_SUCCEEDED_POD + and container_is_succeeded(pod, self.base_container_name) + ) + ) + if should_delete_pod: + self.log.info("Deleting pod: %s", pod.metadata.name) + self.pod_manager.delete_pod(pod) + else: + self.log.info("Skipping deleting pod: %s", pod.metadata.name)
+ + def _build_find_pod_label_selector(self, context: Context | None = None, *, exclude_checked=True) -> str: + labels = { + **self.labels, + **self._get_ti_pod_labels(context, include_try_number=False), + } + label_strings = [f"{label_id}={label}" for label_id, label in sorted(labels.items())] + labels_value = ",".join(label_strings) + if exclude_checked: + labels_value += f",{self.POD_CHECKED_KEY}!=True" + labels_value += ",!airflow-worker" + return labels_value + + @staticmethod + def _set_name(name: str | None) -> str | None: + if name is not None: + validate_key(name, max_length=220) + return re.sub(r"[^a-z0-9-]+", "-", name.lower()) + return None + +
[docs] def patch_already_checked(self, pod: k8s.V1Pod, *, reraise=True): + """Add an "already checked" annotation to ensure we don't reattach on retries.""" + with _optionally_suppress(reraise=reraise): + self.client.patch_namespaced_pod( + name=pod.metadata.name, + namespace=pod.metadata.namespace, + body={"metadata": {"labels": {self.POD_CHECKED_KEY: "True"}}}, + )
+ +
[docs] def on_kill(self) -> None: + self._killed = True + if self.pod: + pod = self.pod + kwargs = { + "name": pod.metadata.name, + "namespace": pod.metadata.namespace, + } + if self.termination_grace_period is not None: + kwargs.update(grace_period_seconds=self.termination_grace_period) + + try: + self.client.delete_namespaced_pod(**kwargs) + except kubernetes.client.exceptions.ApiException: + self.log.exception("Unable to delete pod %s", self.pod.metadata.name)
+ +
[docs] def build_pod_request_obj(self, context: Context | None = None) -> k8s.V1Pod: + """ + Return V1Pod object based on pod template file, full pod spec, and other operator parameters. + + The V1Pod attributes are derived (in order of precedence) from operator params, full pod spec, pod + template file. + """ + self.log.debug("Creating pod for KubernetesPodOperator task %s", self.task_id) + if self.pod_template_file: + self.log.debug("Pod template file found, will parse for base pod") + pod_template = pod_generator.PodGenerator.deserialize_model_file(self.pod_template_file) + if self.full_pod_spec: + pod_template = PodGenerator.reconcile_pods(pod_template, self.full_pod_spec) + elif self.pod_template_dict: + self.log.debug("Pod template dict found, will parse for base pod") + pod_template = pod_generator.PodGenerator.deserialize_model_dict(self.pod_template_dict) + if self.full_pod_spec: + pod_template = PodGenerator.reconcile_pods(pod_template, self.full_pod_spec) + elif self.full_pod_spec: + pod_template = self.full_pod_spec + else: + pod_template = k8s.V1Pod(metadata=k8s.V1ObjectMeta()) + + pod = k8s.V1Pod( + api_version="v1", + kind="Pod", + metadata=k8s.V1ObjectMeta( + namespace=self.namespace, + labels=self.labels, + name=self.name, + annotations=self.annotations, + ), + spec=k8s.V1PodSpec( + node_selector=self.node_selector, + affinity=self.affinity, + tolerations=self.tolerations, + init_containers=self.init_containers, + host_aliases=self.host_aliases, + containers=[ + k8s.V1Container( + image=self.image, + name=self.base_container_name, + command=self.cmds, + ports=self.ports, + image_pull_policy=self.image_pull_policy, + resources=self.container_resources, + volume_mounts=self.volume_mounts, + args=self.arguments, + env=self.env_vars, + env_from=self.env_from, + security_context=self.container_security_context, + termination_message_policy=self.termination_message_policy, + ) + ], + image_pull_secrets=self.image_pull_secrets, + service_account_name=self.service_account_name, + host_network=self.hostnetwork, + hostname=self.hostname, + subdomain=self.subdomain, + security_context=self.security_context, + dns_policy=self.dnspolicy, + dns_config=self.dns_config, + scheduler_name=self.schedulername, + restart_policy="Never", + priority_class_name=self.priority_class_name, + volumes=self.volumes, + active_deadline_seconds=self.active_deadline_seconds, + ), + ) + + pod = PodGenerator.reconcile_pods(pod_template, pod) + + if not pod.metadata.name: + pod.metadata.name = create_unique_id( + task_id=self.task_id, unique=self.random_name_suffix, max_length=POD_NAME_MAX_LENGTH + ) + elif self.random_name_suffix: + # user has supplied pod name, we're just adding suffix + pod.metadata.name = add_unique_suffix(name=pod.metadata.name) + + if not pod.metadata.namespace: + hook_namespace = self.hook.get_namespace() + pod_namespace = self.namespace or hook_namespace or self._incluster_namespace or "default" + pod.metadata.namespace = pod_namespace + + for secret in self.secrets: + self.log.debug("Adding secret to task %s", self.task_id) + pod = secret.attach_to_pod(pod) + if self.do_xcom_push: + self.log.debug("Adding xcom sidecar to task %s", self.task_id) + pod = xcom_sidecar.add_xcom_sidecar( + pod, + sidecar_container_image=self.hook.get_xcom_sidecar_container_image(), + sidecar_container_resources=self.hook.get_xcom_sidecar_container_resources(), + ) + + labels = self._get_ti_pod_labels(context) + self.log.info("Building pod %s with labels: %s", pod.metadata.name, labels) + + # Merge Pod Identifying labels with labels passed to operator + pod.metadata.labels.update(labels) + # Add Airflow Version to the label + # And a label to identify that pod is launched by KubernetesPodOperator + pod.metadata.labels.update( + { + "airflow_version": airflow_version.replace("+", "-"), + "airflow_kpo_in_cluster": str(self.hook.is_in_cluster), + } + ) + pod_mutation_hook(pod) + return pod
+ +
[docs] def dry_run(self) -> None: + """ + Print out the pod definition that would be created by this operator. + + Does not include labels specific to the task instance (since there isn't + one in a dry_run) and excludes all empty elements. + """ + pod = self.build_pod_request_obj() + print(yaml.dump(prune_dict(pod.to_dict(), mode="strict")))
+ + +class _optionally_suppress(AbstractContextManager): + """ + Returns context manager that will swallow and log exceptions. + + By default swallows descendents of Exception, but you can provide other classes through + the vararg ``exceptions``. + + Suppression behavior can be disabled with reraise=True. + + :meta private: + """ + + def __init__(self, *exceptions, reraise=False): + self._exceptions = exceptions or (Exception,) + self.reraise = reraise + self.exception = None + + def __enter__(self): + return self + + def __exit__(self, exctype, excinst, exctb): + error = exctype is not None + matching_error = error and issubclass(exctype, self._exceptions) + if (error and not matching_error) or (matching_error and self.reraise): + return False + elif matching_error: + self.exception = excinst + logger = logging.getLogger(__name__) + logger.exception(excinst) + return True +
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/resource.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/resource.html new file mode 100644 index 00000000000..af0e606d3f0 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/resource.html @@ -0,0 +1,1038 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.operators.resource — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.operators.resource

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""Manage a Kubernetes Resource."""
+
+from __future__ import annotations
+
+import os
+from functools import cached_property
+from typing import TYPE_CHECKING, Sequence
+
+import yaml
+from kubernetes.utils import create_from_yaml
+
+from airflow.exceptions import AirflowException
+from airflow.models import BaseOperator
+from airflow.providers.cncf.kubernetes.hooks.kubernetes import KubernetesHook
+from airflow.providers.cncf.kubernetes.utils.delete_from import delete_from_yaml
+from airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator import k8s_resource_iterator
+
+if TYPE_CHECKING:
+    from kubernetes.client import ApiClient, CustomObjectsApi
+
+__all__ = ["KubernetesCreateResourceOperator", "KubernetesDeleteResourceOperator"]
+
+
+class KubernetesResourceBaseOperator(BaseOperator):
+    """
+    Abstract base class for all Kubernetes Resource operators.
+
+    :param yaml_conf: string. Contains the kubernetes resources to Create or Delete
+    :param yaml_conf_file: path to the kubernetes resources file (templated)
+    :param namespace: string. Contains the namespace to create all resources inside.
+        The namespace must preexist otherwise the resource creation will fail.
+        If the API object in the yaml file already contains a namespace definition then
+        this parameter has no effect.
+    :param kubernetes_conn_id: The :ref:`kubernetes connection id <howto/connection:kubernetes>`
+        for the Kubernetes cluster.
+    :param namespaced: specified that Kubernetes resource is or isn't in a namespace.
+        This parameter works only when custom_resource_definition parameter is True.
+    """
+
+    template_fields: Sequence[str] = ("yaml_conf", "yaml_conf_file")
+    template_fields_renderers = {"yaml_conf": "yaml"}
+
+    def __init__(
+        self,
+        *,
+        yaml_conf: str | None = None,
+        yaml_conf_file: str | None = None,
+        namespace: str | None = None,
+        kubernetes_conn_id: str | None = KubernetesHook.default_conn_name,
+        custom_resource_definition: bool = False,
+        namespaced: bool = True,
+        config_file: str | None = None,
+        **kwargs,
+    ) -> None:
+        super().__init__(**kwargs)
+        self._namespace = namespace
+        self.kubernetes_conn_id = kubernetes_conn_id
+        self.yaml_conf = yaml_conf
+        self.yaml_conf_file = yaml_conf_file
+        self.custom_resource_definition = custom_resource_definition
+        self.namespaced = namespaced
+        self.config_file = config_file
+
+        if not any([self.yaml_conf, self.yaml_conf_file]):
+            raise AirflowException("One of `yaml_conf` or `yaml_conf_file` arguments must be provided")
+
+    @cached_property
+    def client(self) -> ApiClient:
+        return self.hook.api_client
+
+    @cached_property
+    def custom_object_client(self) -> CustomObjectsApi:
+        return self.hook.custom_object_client
+
+    @cached_property
+    def hook(self) -> KubernetesHook:
+        hook = KubernetesHook(conn_id=self.kubernetes_conn_id, config_file=self.config_file)
+        return hook
+
+    def get_namespace(self) -> str:
+        if self._namespace:
+            return self._namespace
+        else:
+            return self.hook.get_namespace() or "default"
+
+    def get_crd_fields(self, body: dict) -> tuple[str, str, str, str]:
+        api_version = body["apiVersion"]
+        group = api_version[0 : api_version.find("/")]
+        version = api_version[api_version.find("/") + 1 :]
+
+        namespace = None
+        if body.get("metadata"):
+            metadata: dict = body.get("metadata", None)
+            namespace = metadata.get("namespace", None)
+        if namespace is None:
+            namespace = self.get_namespace()
+
+        plural = body["kind"].lower() + "s"
+
+        return group, version, namespace, plural
+
+
+
[docs]class KubernetesCreateResourceOperator(KubernetesResourceBaseOperator): + """Create a resource in a kubernetes.""" + +
[docs] def create_custom_from_yaml_object(self, body: dict): + group, version, namespace, plural = self.get_crd_fields(body) + if self.namespaced: + self.custom_object_client.create_namespaced_custom_object(group, version, namespace, plural, body) + else: + self.custom_object_client.create_cluster_custom_object(group, version, plural, body)
+ + def _create_objects(self, objects): + if not self.custom_resource_definition: + create_from_yaml( + k8s_client=self.client, + yaml_objects=objects, + namespace=self.get_namespace(), + ) + else: + k8s_resource_iterator(self.create_custom_from_yaml_object, objects) + +
[docs] def execute(self, context) -> None: + if self.yaml_conf: + self._create_objects(yaml.safe_load_all(self.yaml_conf)) + elif self.yaml_conf_file and os.path.exists(self.yaml_conf_file): + with open(self.yaml_conf_file) as stream: + self._create_objects(yaml.safe_load_all(stream)) + else: + raise AirflowException("File %s not found", self.yaml_conf_file)
+ + +
[docs]class KubernetesDeleteResourceOperator(KubernetesResourceBaseOperator): + """Delete a resource in a kubernetes.""" + +
[docs] def delete_custom_from_yaml_object(self, body: dict): + name = body["metadata"]["name"] + group, version, namespace, plural = self.get_crd_fields(body) + if self.namespaced: + self.custom_object_client.delete_namespaced_custom_object(group, version, namespace, plural, name) + else: + self.custom_object_client.delete_cluster_custom_object(group, version, plural, name)
+ + def _delete_objects(self, objects): + if not self.custom_resource_definition: + delete_from_yaml( + k8s_client=self.client, + yaml_objects=objects, + namespace=self.get_namespace(), + ) + else: + k8s_resource_iterator(self.delete_custom_from_yaml_object, objects) + +
[docs] def execute(self, context) -> None: + if self.yaml_conf: + self._delete_objects(yaml.safe_load_all(self.yaml_conf)) + elif self.yaml_conf_file and os.path.exists(self.yaml_conf_file): + with open(self.yaml_conf_file) as stream: + self._delete_objects(yaml.safe_load_all(stream)) + else: + raise AirflowException("File %s not found", self.yaml_conf_file)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/spark_kubernetes.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/spark_kubernetes.html new file mode 100644 index 00000000000..6801a926cbc --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/operators/spark_kubernetes.html @@ -0,0 +1,1169 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.operators.spark_kubernetes — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.operators.spark_kubernetes

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import re
+from functools import cached_property
+from pathlib import Path
+from typing import TYPE_CHECKING, Any
+
+from kubernetes.client import CoreV1Api, CustomObjectsApi, models as k8s
+
+from airflow.exceptions import AirflowException
+from airflow.providers.cncf.kubernetes import pod_generator
+from airflow.providers.cncf.kubernetes.hooks.kubernetes import KubernetesHook, _load_body_to_dict
+from airflow.providers.cncf.kubernetes.kubernetes_helper_functions import add_unique_suffix
+from airflow.providers.cncf.kubernetes.operators.custom_object_launcher import CustomObjectLauncher
+from airflow.providers.cncf.kubernetes.operators.pod import KubernetesPodOperator
+from airflow.providers.cncf.kubernetes.pod_generator import MAX_LABEL_LEN, PodGenerator
+from airflow.providers.cncf.kubernetes.utils.pod_manager import PodManager
+from airflow.utils.helpers import prune_dict
+
+if TYPE_CHECKING:
+    import jinja2
+
+    from airflow.utils.context import Context
+
+
+
[docs]class SparkKubernetesOperator(KubernetesPodOperator): + """ + Creates sparkApplication object in kubernetes cluster. + + .. seealso:: + For more detail about Spark Application Object have a look at the reference: + https://github.com/GoogleCloudPlatform/spark-on-k8s-operator/blob/v1beta2-1.3.3-3.1.1/docs/api-docs.md#sparkapplication + + :param application_file: filepath to kubernetes custom_resource_definition of sparkApplication + :param kubernetes_conn_id: the connection to Kubernetes cluster + :param image: Docker image you wish to launch. Defaults to hub.docker.com, + :param code_path: path to the spark code in image, + :param namespace: kubernetes namespace to put sparkApplication + :param cluster_context: context of the cluster + :param application_file: yaml file if passed + :param get_logs: get the stdout of the container as logs of the tasks. + :param do_xcom_push: If True, the content of the file + /airflow/xcom/return.json in the container will also be pushed to an + XCom when the container completes. + :param success_run_history_limit: Number of past successful runs of the application to keep. + :param delete_on_termination: What to do when the pod reaches its final + state, or the execution is interrupted. If True (default), delete the + pod; if False, leave the pod. + :param startup_timeout_seconds: timeout in seconds to startup the pod. + :param log_events_on_failure: Log the pod's events if a failure occurs + :param reattach_on_restart: if the scheduler dies while the pod is running, reattach and monitor + """ + +
[docs] template_fields = ["application_file", "namespace", "template_spec"]
+
[docs] template_fields_renderers = {"template_spec": "py"}
+
[docs] template_ext = ("yaml", "yml", "json")
+
[docs] ui_color = "#f4a460"
+ +
[docs] BASE_CONTAINER_NAME = "spark-kubernetes-driver"
+ + def __init__( + self, + *, + image: str | None = None, + code_path: str | None = None, + namespace: str = "default", + name: str = "default", + application_file: str | None = None, + template_spec=None, + get_logs: bool = True, + do_xcom_push: bool = False, + success_run_history_limit: int = 1, + startup_timeout_seconds=600, + log_events_on_failure: bool = False, + reattach_on_restart: bool = True, + delete_on_termination: bool = True, + kubernetes_conn_id: str = "kubernetes_default", + **kwargs, + ) -> None: + if kwargs.get("xcom_push") is not None: + raise AirflowException("'xcom_push' was deprecated, use 'do_xcom_push' instead") + super().__init__(name=name, **kwargs) + self.image = image + self.code_path = code_path + self.application_file = application_file + self.template_spec = template_spec + self.name = self.create_job_name() + self.kubernetes_conn_id = kubernetes_conn_id + self.startup_timeout_seconds = startup_timeout_seconds + self.reattach_on_restart = reattach_on_restart + self.delete_on_termination = delete_on_termination + self.do_xcom_push = do_xcom_push + self.namespace = namespace + self.get_logs = get_logs + self.log_events_on_failure = log_events_on_failure + self.success_run_history_limit = success_run_history_limit + + if self.base_container_name != self.BASE_CONTAINER_NAME: + self.log.warning( + "base_container_name is not supported and will be overridden to %s", self.BASE_CONTAINER_NAME + ) + self.base_container_name = self.BASE_CONTAINER_NAME + + if self.get_logs and self.container_logs != self.BASE_CONTAINER_NAME: + self.log.warning( + "container_logs is not supported and will be overridden to %s", self.BASE_CONTAINER_NAME + ) + self.container_logs = [self.BASE_CONTAINER_NAME] + + def _render_nested_template_fields( + self, + content: Any, + context: Context, + jinja_env: jinja2.Environment, + seen_oids: set, + ) -> None: + if id(content) not in seen_oids and isinstance(content, k8s.V1EnvVar): + seen_oids.add(id(content)) + self._do_render_template_fields(content, ("value", "name"), context, jinja_env, seen_oids) + return + + super()._render_nested_template_fields(content, context, jinja_env, seen_oids) + +
[docs] def manage_template_specs(self): + if self.application_file: + try: + filepath = Path(self.application_file.rstrip()).resolve(strict=True) + except (FileNotFoundError, OSError, RuntimeError, ValueError): + application_file_body = self.application_file + else: + application_file_body = filepath.read_text() + template_body = _load_body_to_dict(application_file_body) + if not isinstance(template_body, dict): + msg = f"application_file body can't transformed into the dictionary:\n{application_file_body}" + raise TypeError(msg) + elif self.template_spec: + template_body = self.template_spec + else: + raise AirflowException("either application_file or template_spec should be passed") + if "spark" not in template_body: + template_body = {"spark": template_body} + return template_body
+ +
[docs] def create_job_name(self): + initial_name = add_unique_suffix(name=self.task_id, max_len=MAX_LABEL_LEN) + return re.sub(r"[^a-z0-9-]+", "-", initial_name.lower())
+ + @staticmethod + def _get_pod_identifying_label_string(labels) -> str: + filtered_labels = {label_id: label for label_id, label in labels.items() if label_id != "try_number"} + return ",".join([label_id + "=" + label for label_id, label in sorted(filtered_labels.items())]) + + @staticmethod +
[docs] def create_labels_for_pod(context: dict | None = None, include_try_number: bool = True) -> dict: + """ + Generate labels for the pod to track the pod in case of Operator crash. + + :param include_try_number: add try number to labels + :param context: task context provided by airflow DAG + :return: dict. + """ + if not context: + return {} + + ti = context["ti"] + run_id = context["run_id"] + + labels = { + "dag_id": ti.dag_id, + "task_id": ti.task_id, + "run_id": run_id, + "spark_kubernetes_operator": "True", + # 'execution_date': context['ts'], + # 'try_number': context['ti'].try_number, + } + + # If running on Airflow 2.3+: + map_index = getattr(ti, "map_index", -1) + if map_index >= 0: + labels["map_index"] = map_index + + if include_try_number: + labels.update(try_number=ti.try_number) + + # In the case of sub dags this is just useful + if context["dag"].is_subdag: + labels["parent_dag_id"] = context["dag"].parent_dag.dag_id + # Ensure that label is valid for Kube, + # and if not truncate/remove invalid chars and replace with short hash. + for label_id, label in labels.items(): + safe_label = pod_generator.make_safe_label_value(str(label)) + labels[label_id] = safe_label + return labels
+ + @cached_property +
[docs] def pod_manager(self) -> PodManager: + return PodManager(kube_client=self.client)
+ + @staticmethod + def _try_numbers_match(context, pod) -> bool: + return pod.metadata.labels["try_number"] == context["ti"].try_number + + @property +
[docs] def template_body(self): + """Templated body for CustomObjectLauncher.""" + return self.manage_template_specs()
+ +
[docs] def find_spark_job(self, context): + labels = self.create_labels_for_pod(context, include_try_number=False) + label_selector = self._get_pod_identifying_label_string(labels) + ",spark-role=driver" + pod_list = self.client.list_namespaced_pod(self.namespace, label_selector=label_selector).items + + pod = None + if len(pod_list) > 1: # and self.reattach_on_restart: + raise AirflowException(f"More than one pod running with labels: {label_selector}") + elif len(pod_list) == 1: + pod = pod_list[0] + self.log.info( + "Found matching driver pod %s with labels %s", pod.metadata.name, pod.metadata.labels + ) + self.log.info("`try_number` of task_instance: %s", context["ti"].try_number) + self.log.info("`try_number` of pod: %s", pod.metadata.labels["try_number"]) + return pod
+ +
[docs] def get_or_create_spark_crd(self, launcher: CustomObjectLauncher, context) -> k8s.V1Pod: + if self.reattach_on_restart: + driver_pod = self.find_spark_job(context) + if driver_pod: + return driver_pod + + driver_pod, spark_obj_spec = launcher.start_spark_job( + image=self.image, code_path=self.code_path, startup_timeout=self.startup_timeout_seconds + ) + return driver_pod
+ +
[docs] def process_pod_deletion(self, pod, *, reraise=True): + if pod is not None: + if self.delete_on_termination: + self.log.info("Deleting spark job: %s", pod.metadata.name.replace("-driver", "")) + self.launcher.delete_spark_job(pod.metadata.name.replace("-driver", "")) + else: + self.log.info("skipping deleting spark job: %s", pod.metadata.name)
+ + @cached_property +
[docs] def hook(self) -> KubernetesHook: + hook = KubernetesHook( + conn_id=self.kubernetes_conn_id, + in_cluster=self.in_cluster or self.template_body.get("kubernetes", {}).get("in_cluster", False), + config_file=self.config_file + or self.template_body.get("kubernetes", {}).get("kube_config_file", None), + cluster_context=self.cluster_context + or self.template_body.get("kubernetes", {}).get("cluster_context", None), + ) + return hook
+ + @cached_property +
[docs] def client(self) -> CoreV1Api: + return self.hook.core_v1_client
+ + @cached_property +
[docs] def custom_obj_api(self) -> CustomObjectsApi: + return CustomObjectsApi()
+ +
[docs] def execute(self, context: Context): + self.log.info("Creating sparkApplication.") + self.launcher = CustomObjectLauncher( + name=self.name, + namespace=self.namespace, + kube_client=self.client, + custom_obj_api=self.custom_obj_api, + template_body=self.template_body, + ) + self.pod = self.get_or_create_spark_crd(self.launcher, context) + self.pod_request_obj = self.launcher.pod_spec + + return super().execute(context=context)
+ +
[docs] def on_kill(self) -> None: + if self.launcher: + self.log.debug("Deleting spark job for task %s", self.task_id) + self.launcher.delete_spark_job()
+ +
[docs] def patch_already_checked(self, pod: k8s.V1Pod, *, reraise=True): + """Add an "already checked" annotation to ensure we don't reattach on retries.""" + pod.metadata.labels["already_checked"] = "True" + body = PodGenerator.serialize_pod(pod) + self.client.patch_namespaced_pod(pod.metadata.name, pod.metadata.namespace, body)
+ +
[docs] def dry_run(self) -> None: + """Print out the spark job that would be created by this operator.""" + print(prune_dict(self.launcher.body, mode="strict"))
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/pod_generator.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/pod_generator.html new file mode 100644 index 00000000000..782eff1b8fe --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/pod_generator.html @@ -0,0 +1,1536 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.pod_generator — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.pod_generator

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""
+Pod generator.
+
+This module provides an interface between the previous Pod
+API and outputs a kubernetes.client.models.V1Pod.
+The advantage being that the full Kubernetes API
+is supported and no serialization need be written.
+"""
+
+from __future__ import annotations
+
+import copy
+import logging
+import os
+import warnings
+from functools import reduce
+from typing import TYPE_CHECKING
+
+import re2
+from dateutil import parser
+from deprecated import deprecated
+from kubernetes.client import models as k8s
+from kubernetes.client.api_client import ApiClient
+
+from airflow.exceptions import (
+    AirflowConfigException,
+    AirflowException,
+    AirflowProviderDeprecationWarning,
+)
+from airflow.providers.cncf.kubernetes.kubernetes_helper_functions import (
+    POD_NAME_MAX_LENGTH,
+    add_pod_suffix,
+    add_unique_suffix,
+    rand_str,
+)
+from airflow.providers.cncf.kubernetes.pod_generator_deprecated import (
+    PodDefaults,
+    PodGenerator as PodGeneratorDeprecated,
+)
+from airflow.utils import yaml
+from airflow.utils.hashlib_wrapper import md5
+from airflow.version import version as airflow_version
+
+if TYPE_CHECKING:
+    import datetime
+
+
[docs]log = logging.getLogger(__name__)
+ +
[docs]MAX_LABEL_LEN = 63
+ + +
[docs]class PodMutationHookException(AirflowException): + """Raised when exception happens during Pod Mutation Hook execution."""
+ + +
[docs]class PodReconciliationError(AirflowException): + """Raised when an error is encountered while trying to merge pod configs."""
+ + +
[docs]def make_safe_label_value(string: str) -> str: + """ + Normalize a provided label to be of valid length and characters. + + Valid label values must be 63 characters or less and must be empty or begin and + end with an alphanumeric character ([a-z0-9A-Z]) with dashes (-), underscores (_), + dots (.), and alphanumerics between. + + If the label value is greater than 63 chars once made safe, or differs in any + way from the original value sent to this function, then we need to truncate to + 53 chars, and append it with a unique hash. + """ + safe_label = re2.sub(r"^[^a-z0-9A-Z]*|[^a-zA-Z0-9_\-\.]|[^a-z0-9A-Z]*$", "", string) + + if len(safe_label) > MAX_LABEL_LEN or string != safe_label: + safe_hash = md5(string.encode()).hexdigest()[:9] + safe_label = safe_label[: MAX_LABEL_LEN - len(safe_hash) - 1] + "-" + safe_hash + + return safe_label
+ + +
[docs]def datetime_to_label_safe_datestring(datetime_obj: datetime.datetime) -> str: + """ + Transform a datetime string to use as a label. + + Kubernetes doesn't like ":" in labels, since ISO datetime format uses ":" but + not "_" let's + replace ":" with "_" + + :param datetime_obj: datetime.datetime object + :return: ISO-like string representing the datetime + """ + return datetime_obj.isoformat().replace(":", "_").replace("+", "_plus_")
+ + +
[docs]def label_safe_datestring_to_datetime(string: str) -> datetime.datetime: + """ + Transform a label back to a datetime object. + + Kubernetes doesn't permit ":" in labels. ISO datetime format uses ":" but not + "_", let's + replace ":" with "_" + + :param string: str + :return: datetime.datetime object + """ + return parser.parse(string.replace("_plus_", "+").replace("_", ":"))
+ + +
[docs]class PodGenerator: + """ + Contains Kubernetes Airflow Worker configuration logic. + + Represents a kubernetes pod and manages execution of a single pod. + Any configuration that is container specific gets applied to + the first container in the list of containers. + + :param pod: The fully specified pod. Mutually exclusive with `pod_template_file` + :param pod_template_file: Path to YAML file. Mutually exclusive with `pod` + :param extract_xcom: Whether to bring up a container for xcom + """ + + def __init__( + self, + pod: k8s.V1Pod | None = None, + pod_template_file: str | None = None, + extract_xcom: bool = True, + ): + if not pod_template_file and not pod: + raise AirflowConfigException( + "Podgenerator requires either a `pod` or a `pod_template_file` argument" + ) + if pod_template_file and pod: + raise AirflowConfigException("Cannot pass both `pod` and `pod_template_file` arguments") + + if pod_template_file: + self.ud_pod = self.deserialize_model_file(pod_template_file) + else: + self.ud_pod = pod + + # Attach sidecar + self.extract_xcom = extract_xcom + + @deprecated(reason="This function is deprecated.", category=AirflowProviderDeprecationWarning) +
[docs] def gen_pod(self) -> k8s.V1Pod: + """Generate pod.""" + result = self.ud_pod + + result.metadata.name = add_pod_suffix(pod_name=result.metadata.name) + + if self.extract_xcom: + result = self.add_xcom_sidecar(result) + + return result
+ + @staticmethod + @deprecated( + reason=( + "This function is deprecated. " + "Please use airflow.providers.cncf.kubernetes.utils.xcom_sidecar.add_xcom_sidecar instead" + ), + category=AirflowProviderDeprecationWarning, + ) +
[docs] def add_xcom_sidecar(pod: k8s.V1Pod) -> k8s.V1Pod: + """Add sidecar.""" + pod_cp = copy.deepcopy(pod) + pod_cp.spec.volumes = pod.spec.volumes or [] + pod_cp.spec.volumes.insert(0, PodDefaults.VOLUME) + pod_cp.spec.containers[0].volume_mounts = pod_cp.spec.containers[0].volume_mounts or [] + pod_cp.spec.containers[0].volume_mounts.insert(0, PodDefaults.VOLUME_MOUNT) + pod_cp.spec.containers.append(PodDefaults.SIDECAR_CONTAINER) + + return pod_cp
+ + @staticmethod +
[docs] def from_obj(obj) -> dict | k8s.V1Pod | None: + """Convert to pod from obj.""" + if obj is None: + return None + + k8s_legacy_object = obj.get("KubernetesExecutor", None) + k8s_object = obj.get("pod_override", None) + + if k8s_legacy_object and k8s_object: + raise AirflowConfigException( + "Can not have both a legacy and new" + "executor_config object. Please delete the KubernetesExecutor" + "dict and only use the pod_override kubernetes.client.models.V1Pod" + "object." + ) + if not k8s_object and not k8s_legacy_object: + return None + + if isinstance(k8s_object, k8s.V1Pod): + return k8s_object + elif isinstance(k8s_legacy_object, dict): + warnings.warn( + "Using a dictionary for the executor_config is deprecated and will soon be removed." + 'please use a `kubernetes.client.models.V1Pod` class with a "pod_override" key' + " instead. ", + category=AirflowProviderDeprecationWarning, + stacklevel=2, + ) + return PodGenerator.from_legacy_obj(obj) + else: + raise TypeError( + "Cannot convert a non-kubernetes.client.models.V1Pod object into a KubernetesExecutorConfig" + )
+ + @staticmethod +
[docs] def from_legacy_obj(obj) -> k8s.V1Pod | None: + """Convert to pod from obj.""" + if obj is None: + return None + + # We do not want to extract constant here from ExecutorLoader because it is just + # A name in dictionary rather than executor selection mechanism and it causes cyclic import + namespaced = obj.get("KubernetesExecutor", {}) + + if not namespaced: + return None + + resources = namespaced.get("resources") + + if resources is None: + requests = { + "cpu": namespaced.pop("request_cpu", None), + "memory": namespaced.pop("request_memory", None), + "ephemeral-storage": namespaced.get("ephemeral-storage"), # We pop this one in limits + } + limits = { + "cpu": namespaced.pop("limit_cpu", None), + "memory": namespaced.pop("limit_memory", None), + "ephemeral-storage": namespaced.pop("ephemeral-storage", None), + } + all_resources = list(requests.values()) + list(limits.values()) + if all(r is None for r in all_resources): + resources = None + else: + # remove None's so they don't become 0's + requests = {k: v for k, v in requests.items() if v is not None} + limits = {k: v for k, v in limits.items() if v is not None} + resources = k8s.V1ResourceRequirements(requests=requests, limits=limits) + namespaced["resources"] = resources + return PodGeneratorDeprecated(**namespaced).gen_pod()
+ + @staticmethod +
[docs] def reconcile_pods(base_pod: k8s.V1Pod, client_pod: k8s.V1Pod | None) -> k8s.V1Pod: + """ + Merge Kubernetes Pod objects. + + :param base_pod: has the base attributes which are overwritten if they exist + in the client pod and remain if they do not exist in the client_pod + :param client_pod: the pod that the client wants to create. + :return: the merged pods + + This can't be done recursively as certain fields are overwritten and some are concatenated. + """ + if client_pod is None: + return base_pod + + client_pod_cp = copy.deepcopy(client_pod) + client_pod_cp.spec = PodGenerator.reconcile_specs(base_pod.spec, client_pod_cp.spec) + client_pod_cp.metadata = PodGenerator.reconcile_metadata(base_pod.metadata, client_pod_cp.metadata) + client_pod_cp = merge_objects(base_pod, client_pod_cp) + + return client_pod_cp
+ + @staticmethod +
[docs] def reconcile_metadata(base_meta, client_meta): + """ + Merge Kubernetes Metadata objects. + + :param base_meta: has the base attributes which are overwritten if they exist + in the client_meta and remain if they do not exist in the client_meta + :param client_meta: the spec that the client wants to create. + :return: the merged specs + """ + if base_meta and not client_meta: + return base_meta + if not base_meta and client_meta: + return client_meta + elif client_meta and base_meta: + client_meta.labels = merge_objects(base_meta.labels, client_meta.labels) + client_meta.annotations = merge_objects(base_meta.annotations, client_meta.annotations) + extend_object_field(base_meta, client_meta, "managed_fields") + extend_object_field(base_meta, client_meta, "finalizers") + extend_object_field(base_meta, client_meta, "owner_references") + return merge_objects(base_meta, client_meta) + + return None
+ + @staticmethod +
[docs] def reconcile_specs( + base_spec: k8s.V1PodSpec | None, client_spec: k8s.V1PodSpec | None + ) -> k8s.V1PodSpec | None: + """ + Merge Kubernetes PodSpec objects. + + :param base_spec: has the base attributes which are overwritten if they exist + in the client_spec and remain if they do not exist in the client_spec + :param client_spec: the spec that the client wants to create. + :return: the merged specs + """ + if base_spec and not client_spec: + return base_spec + if not base_spec and client_spec: + return client_spec + elif client_spec and base_spec: + client_spec.containers = PodGenerator.reconcile_containers( + base_spec.containers, client_spec.containers + ) + merged_spec = extend_object_field(base_spec, client_spec, "init_containers") + merged_spec = extend_object_field(base_spec, merged_spec, "volumes") + return merge_objects(base_spec, merged_spec) + + return None
+ + @staticmethod +
[docs] def reconcile_containers( + base_containers: list[k8s.V1Container], client_containers: list[k8s.V1Container] + ) -> list[k8s.V1Container]: + """ + Merge Kubernetes Container objects. + + :param base_containers: has the base attributes which are overwritten if they exist + in the client_containers and remain if they do not exist in the client_containers + :param client_containers: the containers that the client wants to create. + :return: the merged containers + + The runs recursively over the list of containers. + """ + if not base_containers: + return client_containers + if not client_containers: + return base_containers + + client_container = client_containers[0] + base_container = base_containers[0] + client_container = extend_object_field(base_container, client_container, "volume_mounts") + client_container = extend_object_field(base_container, client_container, "env") + client_container = extend_object_field(base_container, client_container, "env_from") + client_container = extend_object_field(base_container, client_container, "ports") + client_container = extend_object_field(base_container, client_container, "volume_devices") + client_container = merge_objects(base_container, client_container) + + return [ + client_container, + *PodGenerator.reconcile_containers(base_containers[1:], client_containers[1:]), + ]
+ + @classmethod +
[docs] def construct_pod( + cls, + dag_id: str, + task_id: str, + pod_id: str, + try_number: int, + kube_image: str, + date: datetime.datetime | None, + args: list[str], + pod_override_object: k8s.V1Pod | None, + base_worker_pod: k8s.V1Pod, + namespace: str, + scheduler_job_id: str, + run_id: str | None = None, + map_index: int = -1, + *, + with_mutation_hook: bool = False, + ) -> k8s.V1Pod: + """ + Create a Pod. + + Construct a pod by gathering and consolidating the configuration from 3 places: + - airflow.cfg + - executor_config + - dynamic arguments + """ + if len(pod_id) > POD_NAME_MAX_LENGTH: + warnings.warn( + f"pod_id supplied is longer than {POD_NAME_MAX_LENGTH} characters; " + f"truncating and adding unique suffix.", + UserWarning, + stacklevel=2, + ) + pod_id = add_unique_suffix(name=pod_id, max_len=POD_NAME_MAX_LENGTH) + try: + image = pod_override_object.spec.containers[0].image # type: ignore + if not image: + image = kube_image + except Exception: + image = kube_image + + annotations = { + "dag_id": dag_id, + "task_id": task_id, + "try_number": str(try_number), + } + if map_index >= 0: + annotations["map_index"] = str(map_index) + if date: + annotations["execution_date"] = date.isoformat() + if run_id: + annotations["run_id"] = run_id + + dynamic_pod = k8s.V1Pod( + metadata=k8s.V1ObjectMeta( + namespace=namespace, + annotations=annotations, + name=pod_id, + labels=cls.build_labels_for_k8s_executor_pod( + dag_id=dag_id, + task_id=task_id, + try_number=try_number, + airflow_worker=scheduler_job_id, + map_index=map_index, + execution_date=date, + run_id=run_id, + ), + ), + spec=k8s.V1PodSpec( + containers=[ + k8s.V1Container( + name="base", + args=args, + image=image, + env=[k8s.V1EnvVar(name="AIRFLOW_IS_K8S_EXECUTOR_POD", value="True")], + ) + ] + ), + ) + + # Reconcile the pods starting with the first chronologically, + # Pod from the pod_template_File -> Pod from the K8s executor -> Pod from executor_config arg + pod_list = [base_worker_pod, dynamic_pod, pod_override_object] + + try: + pod = reduce(PodGenerator.reconcile_pods, pod_list) + except Exception as e: + raise PodReconciliationError from e + + if with_mutation_hook: + from airflow.settings import pod_mutation_hook + + try: + pod_mutation_hook(pod) + except Exception as e: + raise PodMutationHookException from e + + return pod
+ + @classmethod + def build_selector_for_k8s_executor_pod( + cls, + *, + dag_id, + task_id, + try_number, + map_index=None, + execution_date=None, + run_id=None, + airflow_worker=None, + ): + """ + Generate selector for kubernetes executor pod. + + :meta private: + """ + labels = cls.build_labels_for_k8s_executor_pod( + dag_id=dag_id, + task_id=task_id, + try_number=try_number, + map_index=map_index, + execution_date=execution_date, + run_id=run_id, + airflow_worker=airflow_worker, + ) + label_strings = [f"{label_id}={label}" for label_id, label in sorted(labels.items())] + selector = ",".join(label_strings) + if not airflow_worker: # this filters out KPO pods even when we don't know the scheduler job id + selector += ",airflow-worker" + return selector + + @classmethod + def build_labels_for_k8s_executor_pod( + cls, + *, + dag_id, + task_id, + try_number, + airflow_worker=None, + map_index=None, + execution_date=None, + run_id=None, + ): + """ + Generate labels for kubernetes executor pod. + + :meta private: + """ + labels = { + "dag_id": make_safe_label_value(dag_id), + "task_id": make_safe_label_value(task_id), + "try_number": str(try_number), + "kubernetes_executor": "True", + "airflow_version": airflow_version.replace("+", "-"), + } + if airflow_worker is not None: + labels["airflow-worker"] = make_safe_label_value(str(airflow_worker)) + if map_index is not None and map_index >= 0: + labels["map_index"] = str(map_index) + if execution_date: + labels["execution_date"] = datetime_to_label_safe_datestring(execution_date) + if run_id: + labels["run_id"] = make_safe_label_value(run_id) + return labels + + @staticmethod +
[docs] def serialize_pod(pod: k8s.V1Pod) -> dict: + """ + Convert a k8s.V1Pod into a json serializable dictionary. + + :param pod: k8s.V1Pod object + :return: Serialized version of the pod returned as dict + """ + api_client = ApiClient() + return api_client.sanitize_for_serialization(pod)
+ + @staticmethod +
[docs] def deserialize_model_file(path: str) -> k8s.V1Pod: + """ + Generate a Pod from a file. + + :param path: Path to the file + :return: a kubernetes.client.models.V1Pod + """ + if os.path.exists(path): + with open(path) as stream: + pod = yaml.safe_load(stream) + else: + pod = None + log.warning("Model file %s does not exist", path) + + return PodGenerator.deserialize_model_dict(pod)
+ + @staticmethod +
[docs] def deserialize_model_dict(pod_dict: dict | None) -> k8s.V1Pod: + """ + Deserializes a Python dictionary to k8s.V1Pod. + + Unfortunately we need access to the private method + ``_ApiClient__deserialize_model`` from the kubernetes client. + This issue is tracked here; https://github.com/kubernetes-client/python/issues/977. + + :param pod_dict: Serialized dict of k8s.V1Pod object + :return: De-serialized k8s.V1Pod + """ + api_client = ApiClient() + return api_client._ApiClient__deserialize_model(pod_dict, k8s.V1Pod)
+ + @staticmethod + @deprecated( + reason="This function is deprecated. Use `add_pod_suffix` in `kubernetes_helper_functions`.", + category=AirflowProviderDeprecationWarning, + ) +
[docs] def make_unique_pod_id(pod_id: str) -> str | None: + r""" + Generate a unique Pod name. + + Kubernetes pod names must consist of one or more lowercase + rfc1035/rfc1123 labels separated by '.' with a maximum length of 253 + characters. + + Name must pass the following regex for validation + ``^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`` + + For more details, see: + https://github.com/kubernetes/kubernetes/blob/release-1.1/docs/design/identifiers.md + + :param pod_id: requested pod name + :return: ``str`` valid Pod name of appropriate length + """ + warnings.warn( + "This function is deprecated. Use `add_pod_suffix` in `kubernetes_helper_functions`.", + AirflowProviderDeprecationWarning, + stacklevel=2, + ) + + if not pod_id: + return None + + max_pod_id_len = 100 # arbitrarily chosen + suffix = rand_str(8) # 8 seems good enough + base_pod_id_len = max_pod_id_len - len(suffix) - 1 # -1 for separator + trimmed_pod_id = pod_id[:base_pod_id_len].rstrip("-.") + return f"{trimmed_pod_id}-{suffix}"
+ + +
[docs]def merge_objects(base_obj, client_obj): + """ + Merge objects. + + :param base_obj: has the base attributes which are overwritten if they exist + in the client_obj and remain if they do not exist in the client_obj + :param client_obj: the object that the client wants to create. + :return: the merged objects + """ + if not base_obj: + return client_obj + if not client_obj: + return base_obj + + client_obj_cp = copy.deepcopy(client_obj) + + if isinstance(base_obj, dict) and isinstance(client_obj_cp, dict): + base_obj_cp = copy.deepcopy(base_obj) + base_obj_cp.update(client_obj_cp) + return base_obj_cp + + for base_key in base_obj.to_dict(): + base_val = getattr(base_obj, base_key, None) + if not getattr(client_obj, base_key, None) and base_val: + if not isinstance(client_obj_cp, dict): + setattr(client_obj_cp, base_key, base_val) + else: + client_obj_cp[base_key] = base_val + return client_obj_cp
+ + +
[docs]def extend_object_field(base_obj, client_obj, field_name): + """ + Add field values to existing objects. + + :param base_obj: an object which has a property `field_name` that is a list + :param client_obj: an object which has a property `field_name` that is a list. + A copy of this object is returned with `field_name` modified + :param field_name: the name of the list field + :return: the client_obj with the property `field_name` being the two properties appended + """ + client_obj_cp = copy.deepcopy(client_obj) + base_obj_field = getattr(base_obj, field_name, None) + client_obj_field = getattr(client_obj, field_name, None) + + if (not isinstance(base_obj_field, list) and base_obj_field is not None) or ( + not isinstance(client_obj_field, list) and client_obj_field is not None + ): + raise ValueError( + f"The chosen field must be a list. Got {type(base_obj_field)} base_object_field " + f"and {type(client_obj_field)} client_object_field." + ) + + if not base_obj_field: + return client_obj_cp + if not client_obj_field: + setattr(client_obj_cp, field_name, base_obj_field) + return client_obj_cp + + appended_fields = base_obj_field + client_obj_field + setattr(client_obj_cp, field_name, appended_fields) + return client_obj_cp
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/pod_generator_deprecated.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/pod_generator_deprecated.html new file mode 100644 index 00000000000..15bd0b1c4a4 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/pod_generator_deprecated.html @@ -0,0 +1,1170 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.pod_generator_deprecated — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.pod_generator_deprecated

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""
+Backwards compatibility for Pod generation.
+
+This module provides an interface between the previous Pod
+API and outputs a kubernetes.client.models.V1Pod.
+The advantage being that the full Kubernetes API
+is supported and no serialization need be written.
+"""
+
+from __future__ import annotations
+
+import copy
+import uuid
+
+import re2
+from kubernetes.client import models as k8s
+
+from airflow.utils.hashlib_wrapper import md5
+
+
[docs]MAX_POD_ID_LEN = 253
+ +
[docs]MAX_LABEL_LEN = 63
+ + +
[docs]class PodDefaults: + """Static defaults for Pods.""" + +
[docs] XCOM_MOUNT_PATH = "/airflow/xcom"
+
[docs] SIDECAR_CONTAINER_NAME = "airflow-xcom-sidecar"
+
[docs] XCOM_CMD = 'trap "exit 0" INT; while true; do sleep 30; done;'
+
[docs] VOLUME_MOUNT = k8s.V1VolumeMount(name="xcom", mount_path=XCOM_MOUNT_PATH)
+
[docs] VOLUME = k8s.V1Volume(name="xcom", empty_dir=k8s.V1EmptyDirVolumeSource())
+
[docs] SIDECAR_CONTAINER = k8s.V1Container( + name=SIDECAR_CONTAINER_NAME, + command=["sh", "-c", XCOM_CMD], + image="alpine", + volume_mounts=[VOLUME_MOUNT], + resources=k8s.V1ResourceRequirements( + requests={ + "cpu": "1m", + } + ), + )
+ + +
[docs]def make_safe_label_value(string): + """ + Normalize a provided label to be of valid length and characters. + + Valid label values must be 63 characters or less and must be empty or begin and + end with an alphanumeric character ([a-z0-9A-Z]) with dashes (-), underscores (_), + dots (.), and alphanumerics between. + + If the label value is greater than 63 chars once made safe, or differs in any + way from the original value sent to this function, then we need to truncate to + 53 chars, and append it with a unique hash. + """ + safe_label = re2.sub(r"^[^a-z0-9A-Z]*|[^a-zA-Z0-9_\-\.]|[^a-z0-9A-Z]*$", "", string) + + if len(safe_label) > MAX_LABEL_LEN or string != safe_label: + safe_hash = md5(string.encode()).hexdigest()[:9] + safe_label = safe_label[: MAX_LABEL_LEN - len(safe_hash) - 1] + "-" + safe_hash + + return safe_label
+ + +
[docs]class PodGenerator: + """ + Contains Kubernetes Airflow Worker configuration logic. + + Represents a kubernetes pod and manages execution of a single pod. + Any configuration that is container specific gets applied to + the first container in the list of containers. + + :param image: The docker image + :param name: name in the metadata section (not the container name) + :param namespace: pod namespace + :param volume_mounts: list of kubernetes volumes mounts + :param envs: A dict containing the environment variables + :param cmds: The command to be run on the first container + :param args: The arguments to be run on the pod + :param labels: labels for the pod metadata + :param node_selectors: node selectors for the pod + :param ports: list of ports. Applies to the first container. + :param volumes: Volumes to be attached to the first container + :param image_pull_policy: Specify a policy to cache or always pull an image + :param restart_policy: The restart policy of the pod + :param image_pull_secrets: Any image pull secrets to be given to the pod. + If more than one secret is required, provide a comma separated list: + secret_a,secret_b + :param init_containers: A list of init containers + :param service_account_name: Identity for processes that run in a Pod + :param resources: Resource requirements for the first containers + :param annotations: annotations for the pod + :param affinity: A dict containing a group of affinity scheduling rules + :param hostnetwork: If True enable host networking on the pod + :param tolerations: A list of kubernetes tolerations + :param security_context: A dict containing the security context for the pod + :param configmaps: Any configmap refs to read ``configmaps`` for environments from. + If more than one configmap is required, provide a comma separated list + configmap_a,configmap_b + :param dnspolicy: Specify a dnspolicy for the pod + :param schedulername: Specify a schedulername for the pod + :param pod: The fully specified pod. Mutually exclusive with `path_or_string` + :param extract_xcom: Whether to bring up a container for xcom + :param priority_class_name: priority class name for the launched Pod + """ + + def __init__( + self, + image: str | None = None, + name: str | None = None, + namespace: str | None = None, + volume_mounts: list[k8s.V1VolumeMount | dict] | None = None, + envs: dict[str, str] | None = None, + cmds: list[str] | None = None, + args: list[str] | None = None, + labels: dict[str, str] | None = None, + node_selectors: dict[str, str] | None = None, + ports: list[k8s.V1ContainerPort | dict] | None = None, + volumes: list[k8s.V1Volume | dict] | None = None, + image_pull_policy: str | None = None, + restart_policy: str | None = None, + image_pull_secrets: str | None = None, + init_containers: list[k8s.V1Container] | None = None, + service_account_name: str | None = None, + resources: k8s.V1ResourceRequirements | dict | None = None, + annotations: dict[str, str] | None = None, + affinity: dict | None = None, + hostnetwork: bool = False, + tolerations: list | None = None, + security_context: k8s.V1PodSecurityContext | dict | None = None, + configmaps: list[str] | None = None, + dnspolicy: str | None = None, + schedulername: str | None = None, + extract_xcom: bool = False, + priority_class_name: str | None = None, + ): + self.pod = k8s.V1Pod() + self.pod.api_version = "v1" + self.pod.kind = "Pod" + + # Pod Metadata + self.metadata = k8s.V1ObjectMeta() + self.metadata.labels = labels + self.metadata.name = name + self.metadata.namespace = namespace + self.metadata.annotations = annotations + + # Pod Container + self.container = k8s.V1Container(name="base") + self.container.image = image + self.container.env = [] + + if envs: + if isinstance(envs, dict): + for key, val in envs.items(): + self.container.env.append(k8s.V1EnvVar(name=key, value=val)) + elif isinstance(envs, list): + self.container.env.extend(envs) + + configmaps = configmaps or [] + self.container.env_from = [] + for configmap in configmaps: + self.container.env_from.append( + k8s.V1EnvFromSource(config_map_ref=k8s.V1ConfigMapEnvSource(name=configmap)) + ) + + self.container.command = cmds or [] + self.container.args = args or [] + if image_pull_policy: + self.container.image_pull_policy = image_pull_policy + self.container.ports = ports or [] + self.container.resources = resources + self.container.volume_mounts = volume_mounts or [] + + # Pod Spec + self.spec = k8s.V1PodSpec(containers=[]) + self.spec.security_context = security_context + self.spec.tolerations = tolerations + if dnspolicy: + self.spec.dns_policy = dnspolicy + self.spec.scheduler_name = schedulername + self.spec.host_network = hostnetwork + self.spec.affinity = affinity + self.spec.service_account_name = service_account_name + self.spec.init_containers = init_containers + self.spec.volumes = volumes or [] + self.spec.node_selector = node_selectors + if restart_policy: + self.spec.restart_policy = restart_policy + self.spec.priority_class_name = priority_class_name + + self.spec.image_pull_secrets = [] + + if image_pull_secrets: + for image_pull_secret in image_pull_secrets.split(","): + self.spec.image_pull_secrets.append(k8s.V1LocalObjectReference(name=image_pull_secret)) + + # Attach sidecar + self.extract_xcom = extract_xcom + +
[docs] def gen_pod(self) -> k8s.V1Pod: + """Generate pod.""" + result = None + + if result is None: + result = self.pod + result.spec = self.spec + result.metadata = self.metadata + result.spec.containers = [self.container] + + result.metadata.name = self.make_unique_pod_id(result.metadata.name) + + if self.extract_xcom: + result = self.add_sidecar(result) + + return result
+ + @staticmethod +
[docs] def add_sidecar(pod: k8s.V1Pod) -> k8s.V1Pod: + """Add sidecar.""" + pod_cp = copy.deepcopy(pod) + pod_cp.spec.volumes = pod.spec.volumes or [] + pod_cp.spec.volumes.insert(0, PodDefaults.VOLUME) + pod_cp.spec.containers[0].volume_mounts = pod_cp.spec.containers[0].volume_mounts or [] + pod_cp.spec.containers[0].volume_mounts.insert(0, PodDefaults.VOLUME_MOUNT) + pod_cp.spec.containers.append(PodDefaults.SIDECAR_CONTAINER) + + return pod_cp
+ + @staticmethod +
[docs] def from_obj(obj) -> k8s.V1Pod | None: + """Convert to pod from obj.""" + if obj is None: + return None + + if isinstance(obj, PodGenerator): + return obj.gen_pod() + + if not isinstance(obj, dict): + raise TypeError( + "Cannot convert a non-dictionary or non-PodGenerator " + "object into a KubernetesExecutorConfig" + ) + + # We do not want to extract constant here from ExecutorLoader because it is just + # A name in dictionary rather than executor selection mechanism and it causes cyclic import + namespaced = obj.get("KubernetesExecutor", {}) + + if not namespaced: + return None + + resources = namespaced.get("resources") + + if resources is None: + requests = { + "cpu": namespaced.get("request_cpu"), + "memory": namespaced.get("request_memory"), + "ephemeral-storage": namespaced.get("ephemeral-storage"), + } + limits = { + "cpu": namespaced.get("limit_cpu"), + "memory": namespaced.get("limit_memory"), + "ephemeral-storage": namespaced.get("ephemeral-storage"), + } + all_resources = list(requests.values()) + list(limits.values()) + if all(r is None for r in all_resources): + resources = None + else: + resources = k8s.V1ResourceRequirements(requests=requests, limits=limits) + namespaced["resources"] = resources + return PodGenerator(**namespaced).gen_pod()
+ + @staticmethod +
[docs] def make_unique_pod_id(dag_id): + r""" + Generate a unique Pod name. + + Kubernetes pod names must be <= 253 chars and must pass the following regex for + validation + ``^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`` + + :param dag_id: a dag_id with only alphanumeric characters + :return: ``str`` valid Pod name of appropriate length + """ + if not dag_id: + return None + + safe_uuid = uuid.uuid4().hex + safe_pod_id = dag_id[: MAX_POD_ID_LEN - len(safe_uuid) - 1] + "-" + safe_uuid + + return safe_pod_id
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/pod_launcher_deprecated.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/pod_launcher_deprecated.html new file mode 100644 index 00000000000..d4b680418c4 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/pod_launcher_deprecated.html @@ -0,0 +1,1181 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.pod_launcher_deprecated — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.pod_launcher_deprecated

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""Launches pods."""
+
+from __future__ import annotations
+
+import json
+import math
+import time
+import warnings
+from typing import TYPE_CHECKING, cast
+
+import pendulum
+import tenacity
+from kubernetes import client, watch
+from kubernetes.client.rest import ApiException
+from kubernetes.stream import stream as kubernetes_stream
+from requests.exceptions import HTTPError
+
+from airflow.exceptions import AirflowException, RemovedInAirflow3Warning
+from airflow.providers.cncf.kubernetes.kube_client import get_kube_client
+from airflow.providers.cncf.kubernetes.pod_generator import PodDefaults
+from airflow.settings import pod_mutation_hook
+from airflow.utils.log.logging_mixin import LoggingMixin
+from airflow.utils.state import State
+
+if TYPE_CHECKING:
+    from kubernetes.client.models.v1_pod import V1Pod
+
+warnings.warn(
+    """
+    Please use :mod: Please use `airflow.providers.cncf.kubernetes.utils.pod_manager`
+
+    To use this module install the provider package by installing this pip package:
+
+    https://pypi.org/project/apache-airflow-providers-cncf-kubernetes/
+
+    """,
+    RemovedInAirflow3Warning,
+    stacklevel=2,
+)
+
+
+
[docs]class PodStatus: + """Status of the pods.""" + +
[docs] PENDING = "pending"
+
[docs] RUNNING = "running"
+
[docs] FAILED = "failed"
+
[docs] SUCCEEDED = "succeeded"
+ + +
[docs]class PodLauncher(LoggingMixin): + """ + Deprecated class for launching pods. + + Please use airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager instead. + """ + + def __init__( + self, + kube_client: client.CoreV1Api = None, + in_cluster: bool = True, + cluster_context: str | None = None, + extract_xcom: bool = False, + ): + """ + Launch pods; DEPRECATED. + + Please use airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager + instead to create the launcher. + + :param kube_client: kubernetes client + :param in_cluster: whether we are in cluster + :param cluster_context: context of the cluster + :param extract_xcom: whether we should extract xcom + """ + super().__init__() + self._client = kube_client or get_kube_client(in_cluster=in_cluster, cluster_context=cluster_context) + self._watch = watch.Watch() + self.extract_xcom = extract_xcom + +
[docs] def run_pod_async(self, pod: V1Pod, **kwargs): + """Run pod asynchronously.""" + pod_mutation_hook(pod) + + sanitized_pod = self._client.api_client.sanitize_for_serialization(pod) + json_pod = json.dumps(sanitized_pod, indent=2) + + self.log.debug("Pod Creation Request: \n%s", json_pod) + try: + resp = self._client.create_namespaced_pod( + body=sanitized_pod, namespace=pod.metadata.namespace, **kwargs + ) + self.log.debug("Pod Creation Response: %s", resp) + except Exception as e: + self.log.exception("Exception when attempting to create Namespaced Pod: %s", json_pod) + raise e + return resp
+ +
[docs] def delete_pod(self, pod: V1Pod): + """Delete pod.""" + try: + self._client.delete_namespaced_pod( + pod.metadata.name, pod.metadata.namespace, body=client.V1DeleteOptions() + ) + except ApiException as e: + # If the pod is already deleted + if str(e.status) != "404": + raise
+ +
[docs] def start_pod(self, pod: V1Pod, startup_timeout: int = 120): + """ + Launch the pod synchronously and wait for completion. + + :param pod: + :param startup_timeout: Timeout for startup of the pod (if pod is pending for too long, fails task) + :return: + """ + resp = self.run_pod_async(pod) + start_time = time.monotonic() + if resp.status.start_time is None: + while self.pod_not_started(pod): + self.log.warning("Pod not yet started: %s", pod.metadata.name) + if time.monotonic() >= start_time + startup_timeout: + raise AirflowException("Pod took too long to start") + time.sleep(1)
+ +
[docs] def monitor_pod(self, pod: V1Pod, get_logs: bool) -> tuple[State, str | None]: + """ + Monitor a pod and return the final state. + + :param pod: pod spec that will be monitored + :param get_logs: whether to read the logs locally + """ + if get_logs: + read_logs_since_sec = None + last_log_time: pendulum.DateTime | None = None + while True: + logs = self.read_pod_logs(pod, timestamps=True, since_seconds=read_logs_since_sec) + for line in logs: + timestamp, message = self.parse_log_line(line.decode("utf-8")) + if timestamp: + last_log_time = cast(pendulum.DateTime, pendulum.parse(timestamp)) + self.log.info(message) + time.sleep(1) + + if not self.base_container_is_running(pod): + break + + self.log.warning("Pod %s log read interrupted", pod.metadata.name) + if last_log_time: + delta = pendulum.now() - last_log_time + # Prefer logs duplication rather than loss + read_logs_since_sec = math.ceil(delta.total_seconds()) + result = None + if self.extract_xcom: + while self.base_container_is_running(pod): + self.log.info("Container %s has state %s", pod.metadata.name, State.RUNNING) + time.sleep(2) + result = self._extract_xcom(pod) + self.log.info(result) + result = json.loads(result) + while self.pod_is_running(pod): + self.log.info("Pod %s has state %s", pod.metadata.name, State.RUNNING) + time.sleep(2) + return self._task_status(self.read_pod(pod)), result
+ +
[docs] def parse_log_line(self, line: str) -> tuple[str | None, str]: + """ + Parse K8s log line and returns the final state. + + :param line: k8s log line + :return: timestamp and log message + """ + timestamp, sep, message = line.strip().partition(" ") + if not sep: + self.log.error( + "Error parsing timestamp (no timestamp in message: %r). " + "Will continue execution but won't update timestamp", + line, + ) + return None, line + return timestamp, message
+ + def _task_status(self, event): + self.log.info("Event: %s had an event of type %s", event.metadata.name, event.status.phase) + status = self.process_status(event.metadata.name, event.status.phase) + return status + +
[docs] def pod_not_started(self, pod: V1Pod): + """Test if pod has not started.""" + state = self._task_status(self.read_pod(pod)) + return state == State.QUEUED
+ +
[docs] def pod_is_running(self, pod: V1Pod): + """Test if pod is running.""" + state = self._task_status(self.read_pod(pod)) + return state not in (State.SUCCESS, State.FAILED)
+ +
[docs] def base_container_is_running(self, pod: V1Pod): + """Test if base container is running.""" + event = self.read_pod(pod) + status = next((s for s in event.status.container_statuses if s.name == "base"), None) + if not status: + return False + return status.state.running is not None
+ + @tenacity.retry(stop=tenacity.stop_after_attempt(3), wait=tenacity.wait_exponential(), reraise=True) +
[docs] def read_pod_logs( + self, + pod: V1Pod, + tail_lines: int | None = None, + timestamps: bool = False, + since_seconds: int | None = None, + ): + """Read log from the pod.""" + additional_kwargs = {} + if since_seconds: + additional_kwargs["since_seconds"] = since_seconds + + if tail_lines: + additional_kwargs["tail_lines"] = tail_lines + + try: + return self._client.read_namespaced_pod_log( + name=pod.metadata.name, + namespace=pod.metadata.namespace, + container="base", + follow=True, + timestamps=timestamps, + _preload_content=False, + **additional_kwargs, + ) + except HTTPError as e: + raise AirflowException(f"There was an error reading the kubernetes API: {e}")
+ + @tenacity.retry(stop=tenacity.stop_after_attempt(3), wait=tenacity.wait_exponential(), reraise=True) +
[docs] def read_pod_events(self, pod): + """Read events from the pod.""" + try: + return self._client.list_namespaced_event( + namespace=pod.metadata.namespace, field_selector=f"involvedObject.name={pod.metadata.name}" + ) + except HTTPError as e: + raise AirflowException(f"There was an error reading the kubernetes API: {e}")
+ + @tenacity.retry(stop=tenacity.stop_after_attempt(3), wait=tenacity.wait_exponential(), reraise=True) +
[docs] def read_pod(self, pod: V1Pod): + """Read pod information.""" + try: + return self._client.read_namespaced_pod(pod.metadata.name, pod.metadata.namespace) + except HTTPError as e: + raise AirflowException(f"There was an error reading the kubernetes API: {e}")
+ + def _extract_xcom(self, pod: V1Pod): + resp = kubernetes_stream( + self._client.connect_get_namespaced_pod_exec, + pod.metadata.name, + pod.metadata.namespace, + container=PodDefaults.SIDECAR_CONTAINER_NAME, + command=["/bin/sh"], + stdin=True, + stdout=True, + stderr=True, + tty=False, + _preload_content=False, + ) + try: + result = self._exec_pod_command(resp, f"cat {PodDefaults.XCOM_MOUNT_PATH}/return.json") + self._exec_pod_command(resp, "kill -s SIGINT 1") + finally: + resp.close() + if result is None: + raise AirflowException(f"Failed to extract xcom from pod: {pod.metadata.name}") + return result + + def _exec_pod_command(self, resp, command): + if resp.is_open(): + self.log.info("Running command... %s\n", command) + resp.write_stdin(command + "\n") + while resp.is_open(): + resp.update(timeout=1) + if resp.peek_stdout(): + return resp.read_stdout() + if resp.peek_stderr(): + self.log.info(resp.read_stderr()) + break + return None + +
[docs] def process_status(self, job_id, status): + """Process status information for the job.""" + status = status.lower() + if status == PodStatus.PENDING: + return State.QUEUED + elif status == PodStatus.FAILED: + self.log.error("Event with job id %s Failed", job_id) + return State.FAILED + elif status == PodStatus.SUCCEEDED: + self.log.info("Event with job id %s Succeeded", job_id) + return State.SUCCESS + elif status == PodStatus.RUNNING: + return State.RUNNING + else: + self.log.error("Event: Invalid state %s on job %s", status, job_id) + return State.FAILED
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/python_kubernetes_script.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/python_kubernetes_script.html new file mode 100644 index 00000000000..2011729518b --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/python_kubernetes_script.html @@ -0,0 +1,953 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.python_kubernetes_script — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.python_kubernetes_script

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""Utilities for using the kubernetes decorator."""
+
+from __future__ import annotations
+
+import os
+from collections import deque
+
+from jinja2 import Environment, FileSystemLoader, StrictUndefined, select_autoescape
+from jinja2.nativetypes import NativeEnvironment
+
+
+def _balance_parens(after_decorator):
+    num_paren = 1
+    after_decorator = deque(after_decorator)
+    after_decorator.popleft()
+    while num_paren:
+        current = after_decorator.popleft()
+        if current == "(":
+            num_paren += 1
+        elif current == ")":
+            num_paren -= 1
+    return "".join(after_decorator)
+
+
+
[docs]def remove_task_decorator(python_source: str, task_decorator_name: str) -> str: + """ + Remove @task.kubernetes or similar as well as @setup and @teardown. + + :param python_source: python source code + :param task_decorator_name: the task decorator name + """ + + def _remove_task_decorator(py_source, decorator_name): + if decorator_name not in py_source: + return python_source + split = python_source.split(decorator_name) + before_decorator, after_decorator = split[0], split[1] + if after_decorator[0] == "(": + after_decorator = _balance_parens(after_decorator) + if after_decorator[0] == "\n": + after_decorator = after_decorator[1:] + return before_decorator + after_decorator + + decorators = ["@setup", "@teardown", task_decorator_name] + for decorator in decorators: + python_source = _remove_task_decorator(python_source, decorator) + return python_source
+ + +
[docs]def write_python_script( + jinja_context: dict, + filename: str, + render_template_as_native_obj: bool = False, +): + """ + Render the python script to a file to execute in the virtual environment. + + :param jinja_context: The jinja context variables to unpack and replace with its placeholders in the + template file. + :param filename: The name of the file to dump the rendered script to. + :param render_template_as_native_obj: If ``True``, rendered Jinja template would be converted + to a native Python object + """ + template_loader = FileSystemLoader(searchpath=os.path.dirname(__file__)) + template_env: Environment + if render_template_as_native_obj: + template_env = NativeEnvironment(loader=template_loader, undefined=StrictUndefined) + else: + template_env = Environment( + loader=template_loader, + undefined=StrictUndefined, + autoescape=select_autoescape(["html", "xml"]), + ) + template = template_env.get_template("python_kubernetes_script.jinja2") + template.stream(**jinja_context).dump(filename)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/resource_convert/configmap.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/resource_convert/configmap.html new file mode 100644 index 00000000000..40615990fd1 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/resource_convert/configmap.html @@ -0,0 +1,913 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.resource_convert.configmap — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.resource_convert.configmap

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from kubernetes.client import models as k8s
+
+
+
[docs]def convert_configmap(configmap_name) -> k8s.V1EnvFromSource: + """ + Convert a str into an k8s object. + + :param configmap_name: config map name + :return: + """ + return k8s.V1EnvFromSource(config_map_ref=k8s.V1ConfigMapEnvSource(name=configmap_name))
+ + +
[docs]def convert_configmap_to_volume( + configmap_info: dict[str, str], +) -> tuple[list[k8s.V1Volume], list[k8s.V1VolumeMount]]: + """ + Convert a dictionary of config_map_name and mount_path into k8s volume mount object and k8s volume. + + :param configmap_info: a dictionary of {config_map_name: mount_path} + :return: + """ + volume_mounts = [] + volumes = [] + for config_name, mount_path in configmap_info.items(): + volume_mounts.append(k8s.V1VolumeMount(mount_path=mount_path, name=config_name)) + volumes.append( + k8s.V1Volume( + name=config_name, + config_map=k8s.V1ConfigMapVolumeSource(name=config_name), + ) + ) + + return volumes, volume_mounts
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/resource_convert/env_variable.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/resource_convert/env_variable.html new file mode 100644 index 00000000000..b3fabfe3e31 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/resource_convert/env_variable.html @@ -0,0 +1,900 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.resource_convert.env_variable — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.resource_convert.env_variable

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from kubernetes.client import models as k8s
+
+from airflow.exceptions import AirflowException
+
+
+
[docs]def convert_env_vars(env_vars) -> list[k8s.V1EnvVar]: + """ + Convert a dictionary of key:value into a list of env_vars. + + :param env_vars: + :return: + """ + if isinstance(env_vars, dict): + res = [] + for k, v in env_vars.items(): + res.append(k8s.V1EnvVar(name=k, value=v)) + return res + elif isinstance(env_vars, list): + if all([isinstance(e, k8s.V1EnvVar) for e in env_vars]): + return env_vars + raise AirflowException(f"Expected dict or list of V1EnvVar, got {type(env_vars)}")
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/resource_convert/secret.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/resource_convert/secret.html new file mode 100644 index 00000000000..fb2e24004bc --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/resource_convert/secret.html @@ -0,0 +1,901 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.resource_convert.secret — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.resource_convert.secret

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from kubernetes.client import models as k8s
+
+
+
[docs]def convert_secret(secret_name: str) -> k8s.V1EnvFromSource: + """ + Convert a str into an k8s object. + + :param secret_name: + :return: + """ + return k8s.V1EnvFromSource(secret_ref=k8s.V1SecretEnvSource(name=secret_name))
+ + +
[docs]def convert_image_pull_secrets(image_pull_secrets: str) -> list[k8s.V1LocalObjectReference]: + """ + Convert an image pull secret name into k8s local object reference. + + :param image_pull_secrets: comma separated string that contains secrets + :return: + """ + secrets = image_pull_secrets.split(",") + return [k8s.V1LocalObjectReference(name=secret) for secret in secrets]
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/secret.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/secret.html new file mode 100644 index 00000000000..cce7c21cabb --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/secret.html @@ -0,0 +1,986 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.secret — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.secret

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""Classes for interacting with Kubernetes API."""
+
+from __future__ import annotations
+
+import copy
+import uuid
+
+from kubernetes.client import models as k8s
+
+from airflow.exceptions import AirflowConfigException
+from airflow.providers.cncf.kubernetes.k8s_model import K8SModel
+
+
+
[docs]class Secret(K8SModel): + """Defines Kubernetes Secret Volume.""" + + def __init__(self, deploy_type, deploy_target, secret, key=None, items=None): + """ + Initialize a Kubernetes Secret Object. + + Used to track requested secrets from the user. + + :param deploy_type: The type of secret deploy in Kubernetes, either `env` or + `volume` + :param deploy_target: (Optional) The environment variable when + `deploy_type` `env` or file path when `deploy_type` `volume` where + expose secret. If `key` is not provided deploy target should be None. + :param secret: Name of the secrets object in Kubernetes + :param key: (Optional) Key of the secret within the Kubernetes Secret + if not provided in `deploy_type` `env` it will mount all secrets in object + :param items: (Optional) items that can be added to a volume secret for specifying projects of + secret keys to paths + https://kubernetes.io/docs/concepts/configuration/secret/#projection-of-secret-keys-to-specific-paths + """ + if deploy_type not in ("env", "volume"): + raise AirflowConfigException("deploy_type must be env or volume") + + self.deploy_type = deploy_type + self.deploy_target = deploy_target + self.items = items or [] + + if deploy_target is not None and deploy_type == "env": + # if deploying to env, capitalize the deploy target + self.deploy_target = deploy_target.upper() + + if key is not None and deploy_target is None: + raise AirflowConfigException("If `key` is set, `deploy_target` should not be None") + + self.secret = secret + self.key = key + +
[docs] def to_env_secret(self) -> k8s.V1EnvVar: + """Store es environment secret.""" + return k8s.V1EnvVar( + name=self.deploy_target, + value_from=k8s.V1EnvVarSource( + secret_key_ref=k8s.V1SecretKeySelector(name=self.secret, key=self.key) + ), + )
+ +
[docs] def to_env_from_secret(self) -> k8s.V1EnvFromSource: + """Read from environment to secret.""" + return k8s.V1EnvFromSource(secret_ref=k8s.V1SecretEnvSource(name=self.secret))
+ +
[docs] def to_volume_secret(self) -> tuple[k8s.V1Volume, k8s.V1VolumeMount]: + """Convert to volume secret.""" + vol_id = f"secretvol{uuid.uuid4()}" + volume = k8s.V1Volume(name=vol_id, secret=k8s.V1SecretVolumeSource(secret_name=self.secret)) + if self.items: + volume.secret.items = self.items + return (volume, k8s.V1VolumeMount(mount_path=self.deploy_target, name=vol_id, read_only=True))
+ +
[docs] def attach_to_pod(self, pod: k8s.V1Pod) -> k8s.V1Pod: + """Attach to pod.""" + cp_pod = copy.deepcopy(pod) + + if self.deploy_type == "volume": + volume, volume_mount = self.to_volume_secret() + if cp_pod.spec.volumes is None: + cp_pod.spec.volumes = [] + cp_pod.spec.volumes.append(volume) + if cp_pod.spec.containers[0].volume_mounts is None: + cp_pod.spec.containers[0].volume_mounts = [] + cp_pod.spec.containers[0].volume_mounts.append(volume_mount) + + if self.deploy_type == "env" and self.key is not None: + env = self.to_env_secret() + if cp_pod.spec.containers[0].env is None: + cp_pod.spec.containers[0].env = [] + cp_pod.spec.containers[0].env.append(env) + + if self.deploy_type == "env" and self.key is None: + env_from = self.to_env_from_secret() + if cp_pod.spec.containers[0].env_from is None: + cp_pod.spec.containers[0].env_from = [] + cp_pod.spec.containers[0].env_from.append(env_from) + + return cp_pod
+ +
[docs] def __eq__(self, other): + return ( + self.deploy_type == other.deploy_type + and self.deploy_target == other.deploy_target + and self.secret == other.secret + and self.key == other.key + )
+ +
[docs] def __repr__(self): + return f"Secret({self.deploy_type}, {self.deploy_target}, {self.secret}, {self.key})"
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/sensors/spark_kubernetes.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/sensors/spark_kubernetes.html new file mode 100644 index 00000000000..ec4655c2559 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/sensors/spark_kubernetes.html @@ -0,0 +1,999 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.sensors.spark_kubernetes — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.sensors.spark_kubernetes

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from functools import cached_property
+from typing import TYPE_CHECKING, Sequence
+
+from kubernetes import client
+
+from airflow.exceptions import AirflowException, AirflowSkipException
+from airflow.providers.cncf.kubernetes.hooks.kubernetes import KubernetesHook
+from airflow.sensors.base import BaseSensorOperator
+
+if TYPE_CHECKING:
+    from airflow.utils.context import Context
+
+
+
[docs]class SparkKubernetesSensor(BaseSensorOperator): + """ + Checks sparkApplication object in kubernetes cluster. + + .. seealso:: + For more detail about Spark Application Object have a look at the reference: + https://github.com/GoogleCloudPlatform/spark-on-k8s-operator/blob/v1beta2-1.1.0-2.4.5/docs/api-docs.md#sparkapplication + + :param application_name: spark Application resource name + :param namespace: the kubernetes namespace where the sparkApplication reside in + :param container_name: the kubernetes container name where the sparkApplication reside in + :param kubernetes_conn_id: The :ref:`kubernetes connection<howto/connection:kubernetes>` + to Kubernetes cluster. + :param attach_log: determines whether logs for driver pod should be appended to the sensor log + :param api_group: kubernetes api group of sparkApplication + :param api_version: kubernetes api version of sparkApplication + """ + +
[docs] template_fields: Sequence[str] = ("application_name", "namespace")
+
[docs] FAILURE_STATES = ("FAILED", "UNKNOWN")
+
[docs] SUCCESS_STATES = ("COMPLETED",)
+ + def __init__( + self, + *, + application_name: str, + attach_log: bool = False, + namespace: str | None = None, + container_name: str = "spark-kubernetes-driver", + kubernetes_conn_id: str = "kubernetes_default", + api_group: str = "sparkoperator.k8s.io", + api_version: str = "v1beta2", + **kwargs, + ) -> None: + super().__init__(**kwargs) + self.application_name = application_name + self.attach_log = attach_log + self.namespace = namespace + self.container_name = container_name + self.kubernetes_conn_id = kubernetes_conn_id + self.api_group = api_group + self.api_version = api_version + + @cached_property +
[docs] def hook(self) -> KubernetesHook: + return KubernetesHook(conn_id=self.kubernetes_conn_id)
+ + def _log_driver(self, application_state: str, response: dict) -> None: + if not self.attach_log: + return + status_info = response["status"] + if "driverInfo" not in status_info: + return + driver_info = status_info["driverInfo"] + if "podName" not in driver_info: + return + driver_pod_name = driver_info["podName"] + namespace = response["metadata"]["namespace"] + log_method = self.log.error if application_state in self.FAILURE_STATES else self.log.info + try: + log = "" + for line in self.hook.get_pod_logs( + driver_pod_name, namespace=namespace, container=self.container_name + ): + log += line.decode() + log_method(log) + except client.rest.ApiException as e: + self.log.warning( + "Could not read logs for pod %s. It may have been disposed.\n" + "Make sure timeToLiveSeconds is set on your SparkApplication spec.\n" + "underlying exception: %s", + driver_pod_name, + e, + ) + +
[docs] def poke(self, context: Context) -> bool: + self.log.info("Poking: %s", self.application_name) + + response = self.hook.get_custom_object( + group=self.api_group, + version=self.api_version, + plural="sparkapplications", + name=self.application_name, + namespace=self.namespace, + ) + + try: + application_state = response["status"]["applicationState"]["state"] + except KeyError: + return False + + if self.attach_log and application_state in self.FAILURE_STATES + self.SUCCESS_STATES: + self._log_driver(application_state, response) + + if application_state in self.FAILURE_STATES: + # TODO: remove this if block when min_airflow_version is set to higher than 2.7.1 + message = f"Spark application failed with state: {application_state}" + if self.soft_fail: + raise AirflowSkipException(message) + raise AirflowException(message) + elif application_state in self.SUCCESS_STATES: + self.log.info("Spark application ended successfully") + return True + else: + self.log.info("Spark application is still in state: %s", application_state) + return False
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/template_rendering.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/template_rendering.html new file mode 100644 index 00000000000..314b70c2335 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/template_rendering.html @@ -0,0 +1,932 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.template_rendering — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.template_rendering

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+from jinja2 import TemplateAssertionError, UndefinedError
+from kubernetes.client.api_client import ApiClient
+
+from airflow.exceptions import AirflowException
+from airflow.providers.cncf.kubernetes.kube_config import KubeConfig
+from airflow.providers.cncf.kubernetes.kubernetes_helper_functions import (
+    create_pod_id,
+)
+from airflow.providers.cncf.kubernetes.pod_generator import PodGenerator
+from airflow.utils.session import NEW_SESSION, provide_session
+
+if TYPE_CHECKING:
+    from airflow.models.taskinstance import TaskInstance
+
+
+
[docs]def render_k8s_pod_yaml(task_instance: TaskInstance) -> dict | None: + """Render k8s pod yaml.""" + kube_config = KubeConfig() + pod = PodGenerator.construct_pod( + dag_id=task_instance.dag_id, + run_id=task_instance.run_id, + task_id=task_instance.task_id, + map_index=task_instance.map_index, + date=None, + pod_id=create_pod_id(task_instance.dag_id, task_instance.task_id), + try_number=task_instance.try_number, + kube_image=kube_config.kube_image, + args=task_instance.command_as_list(), + pod_override_object=PodGenerator.from_obj(task_instance.executor_config), + scheduler_job_id="0", + namespace=kube_config.executor_namespace, + base_worker_pod=PodGenerator.deserialize_model_file(kube_config.pod_template_file), + with_mutation_hook=True, + ) + sanitized_pod = ApiClient().sanitize_for_serialization(pod) + return sanitized_pod
+ + +@provide_session +
[docs]def get_rendered_k8s_spec(task_instance: TaskInstance, session=NEW_SESSION) -> dict | None: + """Fetch rendered template fields from DB.""" + from airflow.models.renderedtifields import RenderedTaskInstanceFields + + rendered_k8s_spec = RenderedTaskInstanceFields.get_k8s_pod_yaml(task_instance, session=session) + if not rendered_k8s_spec: + try: + rendered_k8s_spec = render_k8s_pod_yaml(task_instance) + except (TemplateAssertionError, UndefinedError) as e: + raise AirflowException(f"Unable to render a k8s spec for this taskinstance: {e}") from e + return rendered_k8s_spec
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/triggers/job.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/triggers/job.html new file mode 100644 index 00000000000..4ce03798f00 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/triggers/job.html @@ -0,0 +1,962 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.triggers.job — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.triggers.job

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from functools import cached_property
+from typing import TYPE_CHECKING, Any, AsyncIterator
+
+from airflow.providers.cncf.kubernetes.hooks.kubernetes import AsyncKubernetesHook
+from airflow.triggers.base import BaseTrigger, TriggerEvent
+
+if TYPE_CHECKING:
+    from kubernetes.client import V1Job
+
+
+
[docs]class KubernetesJobTrigger(BaseTrigger): + """ + KubernetesJobTrigger run on the trigger worker to check the state of Job. + + :param job_name: The name of the job. + :param job_namespace: The namespace of the job. + :param kubernetes_conn_id: The :ref:`kubernetes connection id <howto/connection:kubernetes>` + for the Kubernetes cluster. + :param cluster_context: Context that points to kubernetes cluster. + :param config_file: Path to kubeconfig file. + :param poll_interval: Polling period in seconds to check for the status. + :param in_cluster: run kubernetes client with in_cluster configuration. + """ + + def __init__( + self, + job_name: str, + job_namespace: str, + kubernetes_conn_id: str | None = None, + poll_interval: float = 10.0, + cluster_context: str | None = None, + config_file: str | None = None, + in_cluster: bool | None = None, + ): + super().__init__() + self.job_name = job_name + self.job_namespace = job_namespace + self.kubernetes_conn_id = kubernetes_conn_id + self.poll_interval = poll_interval + self.cluster_context = cluster_context + self.config_file = config_file + self.in_cluster = in_cluster + +
[docs] def serialize(self) -> tuple[str, dict[str, Any]]: + """Serialize KubernetesCreateJobTrigger arguments and classpath.""" + return ( + "airflow.providers.cncf.kubernetes.triggers.job.KubernetesJobTrigger", + { + "job_name": self.job_name, + "job_namespace": self.job_namespace, + "kubernetes_conn_id": self.kubernetes_conn_id, + "poll_interval": self.poll_interval, + "cluster_context": self.cluster_context, + "config_file": self.config_file, + "in_cluster": self.in_cluster, + }, + )
+ +
[docs] async def run(self) -> AsyncIterator[TriggerEvent]: # type: ignore[override] + """Get current job status and yield a TriggerEvent.""" + job: V1Job = await self.hook.wait_until_job_complete(name=self.job_name, namespace=self.job_namespace) + job_dict = job.to_dict() + error_message = self.hook.is_job_failed(job=job) + yield TriggerEvent( + { + "name": job.metadata.name, + "namespace": job.metadata.namespace, + "status": "error" if error_message else "success", + "message": f"Job failed with error: {error_message}" + if error_message + else "Job completed successfully", + "job": job_dict, + } + )
+ + @cached_property +
[docs] def hook(self) -> AsyncKubernetesHook: + return AsyncKubernetesHook( + conn_id=self.kubernetes_conn_id, + in_cluster=self.in_cluster, + config_file=self.config_file, + cluster_context=self.cluster_context, + )
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/triggers/pod.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/triggers/pod.html new file mode 100644 index 00000000000..11c43d45074 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/triggers/pod.html @@ -0,0 +1,1173 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.triggers.pod — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.triggers.pod

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import asyncio
+import datetime
+import traceback
+import warnings
+from enum import Enum
+from functools import cached_property
+from typing import TYPE_CHECKING, Any, AsyncIterator
+
+from airflow.exceptions import AirflowProviderDeprecationWarning
+from airflow.providers.cncf.kubernetes.hooks.kubernetes import AsyncKubernetesHook
+from airflow.providers.cncf.kubernetes.utils.pod_manager import (
+    OnFinishAction,
+    PodLaunchTimeoutException,
+    PodPhase,
+)
+from airflow.triggers.base import BaseTrigger, TriggerEvent
+
+if TYPE_CHECKING:
+    from kubernetes_asyncio.client.models import V1Pod
+    from pendulum import DateTime
+
+
+
[docs]class ContainerState(str, Enum): + """ + Possible container states. + + See https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase. + """ + +
[docs] WAITING = "waiting"
+
[docs] RUNNING = "running"
+
[docs] TERMINATED = "terminated"
+
[docs] FAILED = "failed"
+
[docs] UNDEFINED = "undefined"
+ + +
[docs]class KubernetesPodTrigger(BaseTrigger): + """ + KubernetesPodTrigger run on the trigger worker to check the state of Pod. + + :param pod_name: The name of the pod. + :param pod_namespace: The namespace of the pod. + :param kubernetes_conn_id: The :ref:`kubernetes connection id <howto/connection:kubernetes>` + for the Kubernetes cluster. + :param cluster_context: Context that points to kubernetes cluster. + :param config_file: Path to kubeconfig file. + :param poll_interval: Polling period in seconds to check for the status. + :param trigger_start_time: time in Datetime format when the trigger was started + :param in_cluster: run kubernetes client with in_cluster configuration. + :param get_logs: get the stdout of the container as logs of the tasks. + :param startup_timeout: timeout in seconds to start up the pod. + :param startup_check_interval: interval in seconds to check if the pod has already started. + :param on_finish_action: What to do when the pod reaches its final state, or the execution is interrupted. + If "delete_pod", the pod will be deleted regardless its state; if "delete_succeeded_pod", + only succeeded pod will be deleted. You can set to "keep_pod" to keep the pod. + :param should_delete_pod: What to do when the pod reaches its final + state, or the execution is interrupted. If True (default), delete the + pod; if False, leave the pod. + Deprecated - use `on_finish_action` instead. + :param logging_interval: number of seconds to wait before kicking it back to + the operator to print latest logs. If ``None`` will wait until container done. + :param last_log_time: where to resume logs from + """ + + def __init__( + self, + pod_name: str, + pod_namespace: str, + trigger_start_time: datetime.datetime, + base_container_name: str, + kubernetes_conn_id: str | None = None, + poll_interval: float = 2, + cluster_context: str | None = None, + config_file: str | None = None, + in_cluster: bool | None = None, + get_logs: bool = True, + startup_timeout: int = 120, + startup_check_interval: int = 5, + on_finish_action: str = "delete_pod", + should_delete_pod: bool | None = None, + last_log_time: DateTime | None = None, + logging_interval: int | None = None, + ): + super().__init__() + self.pod_name = pod_name + self.pod_namespace = pod_namespace + self.trigger_start_time = trigger_start_time + self.base_container_name = base_container_name + self.kubernetes_conn_id = kubernetes_conn_id + self.poll_interval = poll_interval + self.cluster_context = cluster_context + self.config_file = config_file + self.in_cluster = in_cluster + self.get_logs = get_logs + self.startup_timeout = startup_timeout + self.startup_check_interval = startup_check_interval + self.last_log_time = last_log_time + self.logging_interval = logging_interval + + if should_delete_pod is not None: + warnings.warn( + "`should_delete_pod` parameter is deprecated, please use `on_finish_action`", + category=AirflowProviderDeprecationWarning, + stacklevel=2, + ) + self.on_finish_action = ( + OnFinishAction.DELETE_POD if should_delete_pod else OnFinishAction.KEEP_POD + ) + self.should_delete_pod = should_delete_pod + else: + self.on_finish_action = OnFinishAction(on_finish_action) + self.should_delete_pod = self.on_finish_action == OnFinishAction.DELETE_POD + + self._since_time = None + +
[docs] def serialize(self) -> tuple[str, dict[str, Any]]: + """Serialize KubernetesCreatePodTrigger arguments and classpath.""" + return ( + "airflow.providers.cncf.kubernetes.triggers.pod.KubernetesPodTrigger", + { + "pod_name": self.pod_name, + "pod_namespace": self.pod_namespace, + "base_container_name": self.base_container_name, + "kubernetes_conn_id": self.kubernetes_conn_id, + "poll_interval": self.poll_interval, + "cluster_context": self.cluster_context, + "config_file": self.config_file, + "in_cluster": self.in_cluster, + "get_logs": self.get_logs, + "startup_timeout": self.startup_timeout, + "startup_check_interval": self.startup_check_interval, + "trigger_start_time": self.trigger_start_time, + "should_delete_pod": self.should_delete_pod, + "on_finish_action": self.on_finish_action.value, + "last_log_time": self.last_log_time, + "logging_interval": self.logging_interval, + }, + )
+ +
[docs] async def run(self) -> AsyncIterator[TriggerEvent]: # type: ignore[override] + """Get current pod status and yield a TriggerEvent.""" + self.log.info("Checking pod %r in namespace %r.", self.pod_name, self.pod_namespace) + try: + state = await self._wait_for_pod_start() + if state == ContainerState.TERMINATED: + event = TriggerEvent( + { + "status": "success", + "namespace": self.pod_namespace, + "name": self.pod_name, + "message": "All containers inside pod have started successfully.", + } + ) + elif state == ContainerState.FAILED: + event = TriggerEvent( + { + "status": "failed", + "namespace": self.pod_namespace, + "name": self.pod_name, + "message": "pod failed", + } + ) + else: + event = await self._wait_for_container_completion() + yield event + return + except PodLaunchTimeoutException as e: + message = self._format_exception_description(e) + yield TriggerEvent( + { + "name": self.pod_name, + "namespace": self.pod_namespace, + "status": "timeout", + "message": message, + } + ) + return + except Exception as e: + yield TriggerEvent( + { + "name": self.pod_name, + "namespace": self.pod_namespace, + "status": "error", + "message": str(e), + "stack_trace": traceback.format_exc(), + } + ) + return
+ + def _format_exception_description(self, exc: Exception) -> Any: + if isinstance(exc, PodLaunchTimeoutException): + return exc.args[0] + + description = f"Trigger {self.__class__.__name__} failed with exception {exc.__class__.__name__}." + message = exc.args and exc.args[0] or "" + if message: + description += f"\ntrigger exception message: {message}" + curr_traceback = traceback.format_exc() + description += f"\ntrigger traceback:\n{curr_traceback}" + return description + + async def _wait_for_pod_start(self) -> ContainerState: + """Loops until pod phase leaves ``PENDING`` If timeout is reached, throws error.""" + delta = datetime.datetime.now(tz=datetime.timezone.utc) - self.trigger_start_time + while self.startup_timeout >= delta.total_seconds(): + pod = await self.hook.get_pod(self.pod_name, self.pod_namespace) + if not pod.status.phase == "Pending": + return self.define_container_state(pod) + self.log.info("Still waiting for pod to start. The pod state is %s", pod.status.phase) + await asyncio.sleep(self.startup_check_interval) + delta = datetime.datetime.now(tz=datetime.timezone.utc) - self.trigger_start_time + raise PodLaunchTimeoutException("Pod did not leave 'Pending' phase within specified timeout") + + async def _wait_for_container_completion(self) -> TriggerEvent: + """ + Wait for container completion. + + Waits until container is no longer in running state. If trigger is configured with a logging period, + then will emit an event to resume the task for the purpose of fetching more logs. + """ + time_begin = datetime.datetime.now(tz=datetime.timezone.utc) + time_get_more_logs = None + if self.logging_interval is not None: + time_get_more_logs = time_begin + datetime.timedelta(seconds=self.logging_interval) + while True: + pod = await self.hook.get_pod(self.pod_name, self.pod_namespace) + container_state = self.define_container_state(pod) + if container_state == ContainerState.TERMINATED: + return TriggerEvent( + { + "status": "success", + "namespace": self.pod_namespace, + "name": self.pod_name, + "last_log_time": self.last_log_time, + } + ) + elif container_state == ContainerState.FAILED: + return TriggerEvent( + { + "status": "failed", + "namespace": self.pod_namespace, + "name": self.pod_name, + "message": "Container state failed", + "last_log_time": self.last_log_time, + } + ) + if time_get_more_logs and datetime.datetime.now(tz=datetime.timezone.utc) > time_get_more_logs: + return TriggerEvent( + { + "status": "running", + "last_log_time": self.last_log_time, + "namespace": self.pod_namespace, + "name": self.pod_name, + } + ) + await asyncio.sleep(self.poll_interval) + + def _get_async_hook(self) -> AsyncKubernetesHook: + # TODO: Remove this method when the min version of kubernetes provider is 7.12.0 in Google provider. + return AsyncKubernetesHook( + conn_id=self.kubernetes_conn_id, + in_cluster=self.in_cluster, + config_file=self.config_file, + cluster_context=self.cluster_context, + ) + + @cached_property +
[docs] def hook(self) -> AsyncKubernetesHook: + return self._get_async_hook()
+ +
[docs] def define_container_state(self, pod: V1Pod) -> ContainerState: + pod_containers = pod.status.container_statuses + + if pod_containers is None: + return ContainerState.UNDEFINED + + container = next(c for c in pod_containers if c.name == self.base_container_name) + + for state in (ContainerState.RUNNING, ContainerState.WAITING, ContainerState.TERMINATED): + state_obj = getattr(container.state, state) + if state_obj is not None: + if state != ContainerState.TERMINATED: + return state + else: + return ContainerState.TERMINATED if state_obj.exit_code == 0 else ContainerState.FAILED + return ContainerState.UNDEFINED
+ + @staticmethod +
[docs] def should_wait(pod_phase: PodPhase, container_state: ContainerState) -> bool: + return ( + container_state == ContainerState.WAITING + or container_state == ContainerState.RUNNING + or (container_state == ContainerState.UNDEFINED and pod_phase == PodPhase.PENDING) + )
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/utils/delete_from.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/utils/delete_from.html new file mode 100644 index 00000000000..09a52b7cf10 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/utils/delete_from.html @@ -0,0 +1,1015 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.utils.delete_from — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.utils.delete_from

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# from https://github.com/tomplus/kubernetes_asyncio/pull/239/files
+
+from __future__ import annotations
+
+import re
+from typing import TYPE_CHECKING
+
+from kubernetes import client
+
+if TYPE_CHECKING:
+    from kubernetes.client import ApiClient
+
+
[docs]DEFAULT_DELETION_BODY = client.V1DeleteOptions( + propagation_policy="Background", + grace_period_seconds=5, +)
+ + +
[docs]def delete_from_dict(k8s_client, data, body, namespace, verbose=False, **kwargs): + api_exceptions = [] + + if "List" in data["kind"]: + kind = data["kind"].replace("List", "") + for yml_doc in data["items"]: + if kind != "": + yml_doc["apiVersion"] = data["apiVersion"] + yml_doc["kind"] = kind + try: + _delete_from_yaml_single_item( + k8s_client=k8s_client, + yml_document=yml_doc, + verbose=verbose, + namespace=namespace, + body=body, + **kwargs, + ) + except client.rest.ApiException as api_exception: + api_exceptions.append(api_exception) + else: + try: + _delete_from_yaml_single_item( + k8s_client=k8s_client, + yml_document=data, + verbose=verbose, + namespace=namespace, + body=body, + **kwargs, + ) + except client.rest.ApiException as api_exception: + api_exceptions.append(api_exception) + + if api_exceptions: + raise FailToDeleteError(api_exceptions)
+ + +
[docs]def delete_from_yaml( + *, + k8s_client: ApiClient, + yaml_objects=None, + verbose: bool = False, + namespace: str = "default", + body: dict | None = None, + **kwargs, +): + for yml_document in yaml_objects: + if yml_document is not None: + delete_from_dict( + k8s_client=k8s_client, + data=yml_document, + body=body, + namespace=namespace, + verbose=verbose, + **kwargs, + )
+ + +def _delete_from_yaml_single_item( + *, + k8s_client: ApiClient, + yml_document: dict, + verbose: bool = False, + namespace: str = "default", + body: dict | None = None, + **kwargs, +): + if body is None: + body = DEFAULT_DELETION_BODY + + # get group and version from apiVersion + group, _, version = yml_document["apiVersion"].partition("/") + if version == "": + version = group + group = "core" + # Take care for the case e.g. api_type is "apiextensions.k8s.io" + # Only replace the last instance + group = "".join(group.rsplit(".k8s.io", 1)) + # convert group name from DNS subdomain format to + # python class name convention + group = "".join(word.capitalize() for word in group.split(".")) + fcn_to_call = f"{group}{version.capitalize()}Api" + k8s_api = getattr(client, fcn_to_call)(k8s_client) + # Replace CamelCased action_type into snake_case + kind = yml_document["kind"] + kind = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", kind) + kind = re.sub("([a-z0-9])([A-Z])", r"\1_\2", kind).lower() + + # Decide which namespace we are going to use for deleting the object + # IMPORTANT: the docs namespace takes precedence over the namespace in args + # create_from_yaml_single_item have same behaviour + if "namespace" in yml_document["metadata"]: + namespace = yml_document["metadata"]["namespace"] + name = yml_document["metadata"]["name"] + + # Expect the user to delete namespaced objects more often + resp: client.V1Status + if hasattr(k8s_api, f"delete_namespaced_{kind}"): + resp = getattr(k8s_api, f"delete_namespaced_{kind}")( + name=name, namespace=namespace, body=body, **kwargs + ) + else: + resp = getattr(k8s_api, f"delete_{kind}")(name=name, body=body, **kwargs) + if verbose: + print(f"{kind} deleted. status='{resp.status}'") + return resp + + +
[docs]class FailToDeleteError(Exception): + """For handling error if an error occurred when handling a yaml file during deletion of the resource.""" + + def __init__(self, api_exceptions: list): + self.api_exceptions = api_exceptions + +
[docs] def __str__(self): + msg = "" + for api_exception in self.api_exceptions: + msg += f"Error from server ({api_exception.reason}):{api_exception.body}\n" + return msg
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/utils/k8s_resource_iterator.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/utils/k8s_resource_iterator.html new file mode 100644 index 00000000000..e4a798e9691 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/utils/k8s_resource_iterator.html @@ -0,0 +1,907 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from typing import Callable, Iterator
+
+from kubernetes.utils import FailToCreateError
+
+from airflow.providers.cncf.kubernetes.utils.delete_from import FailToDeleteError
+
+
+
[docs]def k8s_resource_iterator(callback: Callable[[dict], None], resources: Iterator) -> None: + failures: list = [] + for data in resources: + if data is not None: + if "List" in data["kind"]: + kind = data["kind"].replace("List", "") + for yml_doc in data["items"]: + if kind != "": + yml_doc["apiVersion"] = data["apiVersion"] + yml_doc["kind"] = kind + try: + callback(yml_doc) + except (FailToCreateError, FailToDeleteError) as failure: + failures.extend(failure.api_exceptions) + else: + try: + callback(data) + except (FailToCreateError, FailToDeleteError) as failure: + failures.extend(failure.api_exceptions) + if failures: + raise FailToCreateError(failures)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/utils/pod_manager.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/utils/pod_manager.html new file mode 100644 index 00000000000..1c50b9e0daa --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/utils/pod_manager.html @@ -0,0 +1,1684 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.utils.pod_manager — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.utils.pod_manager

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""Launches PODs."""
+
+from __future__ import annotations
+
+import enum
+import itertools
+import json
+import math
+import time
+from collections.abc import Iterable
+from contextlib import closing, suppress
+from dataclasses import dataclass
+from datetime import timedelta
+from typing import TYPE_CHECKING, Callable, Generator, Protocol, cast
+
+import pendulum
+import tenacity
+from deprecated import deprecated
+from kubernetes import client, watch
+from kubernetes.client.rest import ApiException
+from kubernetes.stream import stream as kubernetes_stream
+from pendulum import DateTime
+from pendulum.parsing.exceptions import ParserError
+from typing_extensions import Literal
+from urllib3.exceptions import HTTPError, TimeoutError
+
+from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
+from airflow.providers.cncf.kubernetes.callbacks import ExecutionMode, KubernetesPodOperatorCallback
+from airflow.providers.cncf.kubernetes.pod_generator import PodDefaults
+from airflow.utils.log.logging_mixin import LoggingMixin
+from airflow.utils.timezone import utcnow
+
+if TYPE_CHECKING:
+    from kubernetes.client.models.core_v1_event_list import CoreV1EventList
+    from kubernetes.client.models.v1_container_status import V1ContainerStatus
+    from kubernetes.client.models.v1_pod import V1Pod
+    from urllib3.response import HTTPResponse
+
+
+EMPTY_XCOM_RESULT = "__airflow_xcom_result_empty__"
+"""
+Sentinel for no xcom result.
+
+:meta private:
+"""
+
+
+
[docs]class PodLaunchFailedException(AirflowException): + """When pod launching fails in KubernetesPodOperator."""
+ + +
[docs]def should_retry_start_pod(exception: BaseException) -> bool: + """Check if an Exception indicates a transient error and warrants retrying.""" + if isinstance(exception, ApiException): + return str(exception.status) == "409" + return False
+ + +
[docs]class PodPhase: + """ + Possible pod phases. + + See https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase. + """ + +
[docs] PENDING = "Pending"
+
[docs] RUNNING = "Running"
+
[docs] FAILED = "Failed"
+
[docs] SUCCEEDED = "Succeeded"
+ +
[docs] terminal_states = {FAILED, SUCCEEDED}
+ + +
[docs]class PodOperatorHookProtocol(Protocol): + """ + Protocol to define methods relied upon by KubernetesPodOperator. + + Subclasses of KubernetesPodOperator, such as GKEStartPodOperator, may use + hooks that don't extend KubernetesHook. We use this protocol to document the + methods used by KPO and ensure that these methods exist on such other hooks. + """ + + @property +
[docs] def core_v1_client(self) -> client.CoreV1Api: + """Get authenticated client object."""
+ + @property +
[docs] def is_in_cluster(self) -> bool: + """Expose whether the hook is configured with ``load_incluster_config`` or not."""
+ +
[docs] def get_pod(self, name: str, namespace: str) -> V1Pod: + """Read pod object from kubernetes API."""
+ +
[docs] def get_namespace(self) -> str | None: + """Return the namespace that defined in the connection."""
+ +
[docs] def get_xcom_sidecar_container_image(self) -> str | None: + """Return the xcom sidecar image that defined in the connection."""
+ +
[docs] def get_xcom_sidecar_container_resources(self) -> str | None: + """Return the xcom sidecar resources that defined in the connection."""
+ + +
[docs]def get_container_status(pod: V1Pod, container_name: str) -> V1ContainerStatus | None: + """Retrieve container status.""" + container_statuses = pod.status.container_statuses if pod and pod.status else None + if container_statuses: + # In general the variable container_statuses can store multiple items matching different containers. + # The following generator expression yields all items that have name equal to the container_name. + # The function next() here calls the generator to get only the first value. If there's nothing found + # then None is returned. + return next((x for x in container_statuses if x.name == container_name), None) + return None
+ + +
[docs]def container_is_running(pod: V1Pod, container_name: str) -> bool: + """ + Examine V1Pod ``pod`` to determine whether ``container_name`` is running. + + If that container is present and running, returns True. Returns False otherwise. + """ + container_status = get_container_status(pod, container_name) + if not container_status: + return False + return container_status.state.running is not None
+ + +
[docs]def container_is_completed(pod: V1Pod, container_name: str) -> bool: + """ + Examine V1Pod ``pod`` to determine whether ``container_name`` is completed. + + If that container is present and completed, returns True. Returns False otherwise. + """ + container_status = get_container_status(pod, container_name) + if not container_status: + return False + return container_status.state.terminated is not None
+ + +
[docs]def container_is_succeeded(pod: V1Pod, container_name: str) -> bool: + """ + Examine V1Pod ``pod`` to determine whether ``container_name`` is completed and succeeded. + + If that container is present and completed and succeeded, returns True. Returns False otherwise. + """ + if not container_is_completed(pod, container_name): + return False + + container_status = get_container_status(pod, container_name) + if not container_status: + return False + return container_status.state.terminated.exit_code == 0
+ + +
[docs]def container_is_terminated(pod: V1Pod, container_name: str) -> bool: + """ + Examine V1Pod ``pod`` to determine whether ``container_name`` is terminated. + + If that container is present and terminated, returns True. Returns False otherwise. + """ + container_statuses = pod.status.container_statuses if pod and pod.status else None + if not container_statuses: + return False + container_status = next((x for x in container_statuses if x.name == container_name), None) + if not container_status: + return False + return container_status.state.terminated is not None
+ + +
[docs]def get_container_termination_message(pod: V1Pod, container_name: str): + with suppress(AttributeError, TypeError): + container_statuses = pod.status.container_statuses + container_status = next((x for x in container_statuses if x.name == container_name), None) + return container_status.state.terminated.message if container_status else None
+ + +
[docs]class PodLaunchTimeoutException(AirflowException): + """When pod does not leave the ``Pending`` phase within specified timeout."""
+ + +
[docs]class PodNotFoundException(AirflowException): + """Expected pod does not exist in kube-api."""
+ + +class PodLogsConsumer: + """ + Responsible for pulling pod logs from a stream with checking a container status before reading data. + + This class is a workaround for the issue https://github.com/apache/airflow/issues/23497. + + :param response: HTTP response with logs + :param pod: Pod instance from Kubernetes client + :param pod_manager: Pod manager instance + :param container_name: Name of the container that we're reading logs from + :param post_termination_timeout: (Optional) The period of time in seconds representing for how long time + logs are available after the container termination. + :param read_pod_cache_timeout: (Optional) The container's status cache lifetime. + The container status is cached to reduce API calls. + + :meta private: + """ + + def __init__( + self, + response: HTTPResponse, + pod: V1Pod, + pod_manager: PodManager, + container_name: str, + post_termination_timeout: int = 120, + read_pod_cache_timeout: int = 120, + ): + self.response = response + self.pod = pod + self.pod_manager = pod_manager + self.container_name = container_name + self.post_termination_timeout = post_termination_timeout + self.last_read_pod_at = None + self.read_pod_cache = None + self.read_pod_cache_timeout = read_pod_cache_timeout + + def __iter__(self) -> Generator[bytes, None, None]: + r"""Yield log items divided by the '\n' symbol.""" + incomplete_log_item: list[bytes] = [] + if self.logs_available(): + for data_chunk in self.response.stream(amt=None, decode_content=True): + if b"\n" in data_chunk: + log_items = data_chunk.split(b"\n") + yield from self._extract_log_items(incomplete_log_item, log_items) + incomplete_log_item = self._save_incomplete_log_item(log_items[-1]) + else: + incomplete_log_item.append(data_chunk) + if not self.logs_available(): + break + if incomplete_log_item: + yield b"".join(incomplete_log_item) + + @staticmethod + def _extract_log_items(incomplete_log_item: list[bytes], log_items: list[bytes]): + yield b"".join(incomplete_log_item) + log_items[0] + b"\n" + for x in log_items[1:-1]: + yield x + b"\n" + + @staticmethod + def _save_incomplete_log_item(sub_chunk: bytes): + return [sub_chunk] if [sub_chunk] else [] + + def logs_available(self): + remote_pod = self.read_pod() + if container_is_running(pod=remote_pod, container_name=self.container_name): + return True + container_status = get_container_status(pod=remote_pod, container_name=self.container_name) + state = container_status.state if container_status else None + terminated = state.terminated if state else None + if terminated: + termination_time = terminated.finished_at + if termination_time: + return termination_time + timedelta(seconds=self.post_termination_timeout) > utcnow() + return False + + def read_pod(self): + _now = utcnow() + if ( + self.read_pod_cache is None + or self.last_read_pod_at + timedelta(seconds=self.read_pod_cache_timeout) < _now + ): + self.read_pod_cache = self.pod_manager.read_pod(self.pod) + self.last_read_pod_at = _now + return self.read_pod_cache + + +@dataclass +
[docs]class PodLoggingStatus: + """Return the status of the pod and last log time when exiting from `fetch_container_logs`.""" + +
[docs] running: bool
+
[docs] last_log_time: DateTime | None
+ + +
[docs]class PodManager(LoggingMixin): + """Create, monitor, and otherwise interact with Kubernetes pods for use with the KubernetesPodOperator.""" + + def __init__( + self, + kube_client: client.CoreV1Api, + callbacks: type[KubernetesPodOperatorCallback] | None = None, + progress_callback: Callable[[str], None] | None = None, + ): + """ + Create the launcher. + + :param kube_client: kubernetes client + :param callbacks: + :param progress_callback: Callback function invoked when fetching container log. + This parameter is deprecated, please use ```` + """ + super().__init__() + self._client = kube_client + self._progress_callback = progress_callback + self._watch = watch.Watch() + self._callbacks = callbacks + +
[docs] def run_pod_async(self, pod: V1Pod, **kwargs) -> V1Pod: + """Run POD asynchronously.""" + sanitized_pod = self._client.api_client.sanitize_for_serialization(pod) + json_pod = json.dumps(sanitized_pod, indent=2) + + self.log.debug("Pod Creation Request: \n%s", json_pod) + try: + resp = self._client.create_namespaced_pod( + body=sanitized_pod, namespace=pod.metadata.namespace, **kwargs + ) + self.log.debug("Pod Creation Response: %s", resp) + except Exception as e: + self.log.exception( + "Exception when attempting to create Namespaced Pod: %s", str(json_pod).replace("\n", " ") + ) + raise e + return resp
+ +
[docs] def delete_pod(self, pod: V1Pod) -> None: + """Delete POD.""" + try: + self._client.delete_namespaced_pod( + pod.metadata.name, pod.metadata.namespace, body=client.V1DeleteOptions() + ) + except ApiException as e: + # If the pod is already deleted + if str(e.status) != "404": + raise
+ + @tenacity.retry( + stop=tenacity.stop_after_attempt(3), + wait=tenacity.wait_random_exponential(), + reraise=True, + retry=tenacity.retry_if_exception(should_retry_start_pod), + ) +
[docs] def create_pod(self, pod: V1Pod) -> V1Pod: + """Launch the pod asynchronously.""" + return self.run_pod_async(pod)
+ +
[docs] def await_pod_start( + self, pod: V1Pod, startup_timeout: int = 120, startup_check_interval: int = 1 + ) -> None: + """ + Wait for the pod to reach phase other than ``Pending``. + + :param pod: + :param startup_timeout: Timeout (in seconds) for startup of the pod + (if pod is pending for too long, fails task) + :param startup_check_interval: Interval (in seconds) between checks + :return: + """ + curr_time = time.time() + while True: + remote_pod = self.read_pod(pod) + if remote_pod.status.phase != PodPhase.PENDING: + break + self.log.warning("Pod not yet started: %s", pod.metadata.name) + if time.time() - curr_time >= startup_timeout: + msg = ( + f"Pod took longer than {startup_timeout} seconds to start. " + "Check the pod events in kubernetes to determine why." + ) + raise PodLaunchFailedException(msg) + time.sleep(startup_check_interval)
+ + @deprecated( + reason=( + "Method `follow_container_logs` is deprecated. Use `fetch_container_logs` instead " + "with option `follow=True`." + ), + category=AirflowProviderDeprecationWarning, + ) +
[docs] def follow_container_logs(self, pod: V1Pod, container_name: str) -> PodLoggingStatus: + return self.fetch_container_logs(pod=pod, container_name=container_name, follow=True)
+ + def fetch_container_logs( + self, + pod: V1Pod, + container_name: str, + *, + follow=False, + since_time: DateTime | None = None, + post_termination_timeout: int = 120, + ) -> PodLoggingStatus: + """ + Follow the logs of container and stream to airflow logging. + + Returns when container exits. + + Between when the pod starts and logs being available, there might be a delay due to CSR not approved + and signed yet. In such situation, ApiException is thrown. This is why we are retrying on this + specific exception. + + :meta private: + """ + + def consume_logs(*, since_time: DateTime | None = None) -> tuple[DateTime | None, Exception | None]: + """ + Try to follow container logs until container completes. + + For a long-running container, sometimes the log read may be interrupted + Such errors of this kind are suppressed. + + Returns the last timestamp observed in logs. + """ + exception = None + last_captured_timestamp = None + # We timeout connections after 30 minutes because otherwise they can get + # stuck forever. The 30 is somewhat arbitrary. + # As a consequence, a TimeoutError will be raised no more than 30 minutes + # after starting read. + connection_timeout = 60 * 30 + # We set a shorter read timeout because that helps reduce *connection* timeouts + # (since the connection will be restarted periodically). And with read timeout, + # we don't need to worry about either duplicate messages or losing messages; we + # can safely resume from a few seconds later + read_timeout = 60 * 5 + try: + logs = self.read_pod_logs( + pod=pod, + container_name=container_name, + timestamps=True, + since_seconds=( + math.ceil((pendulum.now() - since_time).total_seconds()) if since_time else None + ), + follow=follow, + post_termination_timeout=post_termination_timeout, + _request_timeout=(connection_timeout, read_timeout), + ) + message_to_log = None + message_timestamp = None + progress_callback_lines = [] + try: + for raw_line in logs: + line = raw_line.decode("utf-8", errors="backslashreplace") + line_timestamp, message = self.parse_log_line(line) + if line_timestamp: # detect new log line + if message_to_log is None: # first line in the log + message_to_log = message + message_timestamp = line_timestamp + progress_callback_lines.append(line) + else: # previous log line is complete + for line in progress_callback_lines: + if self._progress_callback: + self._progress_callback(line) + if self._callbacks: + self._callbacks.progress_callback( + line=line, client=self._client, mode=ExecutionMode.SYNC + ) + if message_to_log is not None: + self.log.info("[%s] %s", container_name, message_to_log) + last_captured_timestamp = message_timestamp + message_to_log = message + message_timestamp = line_timestamp + progress_callback_lines = [line] + else: # continuation of the previous log line + message_to_log = f"{message_to_log}\n{message}" + progress_callback_lines.append(line) + finally: + # log the last line and update the last_captured_timestamp + for line in progress_callback_lines: + if self._progress_callback: + self._progress_callback(line) + if self._callbacks: + self._callbacks.progress_callback( + line=line, client=self._client, mode=ExecutionMode.SYNC + ) + if message_to_log is not None: + self.log.info("[%s] %s", container_name, message_to_log) + last_captured_timestamp = message_timestamp + except TimeoutError as e: + # in case of timeout, increment return time by 2 seconds to avoid + # duplicate log entries + if val := (last_captured_timestamp or since_time): + return val.add(seconds=2), e + except HTTPError as e: + exception = e + self.log.exception( + "Reading of logs interrupted for container %r; will retry.", + container_name, + ) + return last_captured_timestamp or since_time, exception + + # note: `read_pod_logs` follows the logs, so we shouldn't necessarily *need* to + # loop as we do here. But in a long-running process we might temporarily lose connectivity. + # So the looping logic is there to let us resume following the logs. + last_log_time = since_time + while True: + last_log_time, exc = consume_logs(since_time=last_log_time) + if not self.container_is_running(pod, container_name=container_name): + return PodLoggingStatus(running=False, last_log_time=last_log_time) + if not follow: + return PodLoggingStatus(running=True, last_log_time=last_log_time) + else: + # a timeout is a normal thing and we ignore it and resume following logs + if not isinstance(exc, TimeoutError): + self.log.warning( + "Pod %s log read interrupted but container %s still running", + pod.metadata.name, + container_name, + ) + time.sleep(1) + + def _reconcile_requested_log_containers( + self, requested: Iterable[str] | str | bool, actual: list[str], pod_name + ) -> list[str]: + """Return actual containers based on requested.""" + containers_to_log = [] + if actual: + if isinstance(requested, str): + # fetch logs only for requested container if only one container is provided + if requested in actual: + containers_to_log.append(requested) + else: + self.log.error( + "container %s whose logs were requested not found in the pod %s", + requested, + pod_name, + ) + elif isinstance(requested, bool): + # if True is provided, get logs for all the containers + if requested is True: + containers_to_log.extend(actual) + else: + self.log.error( + "False is not a valid value for container_logs", + ) + else: + # if a sequence of containers are provided, iterate for every container in the pod + if isinstance(requested, Iterable): + for container in requested: + if container in actual: + containers_to_log.append(container) + else: + self.log.error( + "Container %s whose logs were requests not found in the pod %s", + container, + pod_name, + ) + else: + self.log.error( + "Invalid type %s specified for container names input parameter", type(requested) + ) + else: + self.log.error("Could not retrieve containers for the pod: %s", pod_name) + return containers_to_log + + def fetch_requested_container_logs( + self, pod: V1Pod, containers: Iterable[str] | str | Literal[True], follow_logs=False + ) -> list[PodLoggingStatus]: + """ + Follow the logs of containers in the specified pod and publish it to airflow logging. + + Returns when all the containers exit. + + :meta private: + """ + pod_logging_statuses = [] + all_containers = self.get_container_names(pod) + containers_to_log = self._reconcile_requested_log_containers( + requested=containers, + actual=all_containers, + pod_name=pod.metadata.name, + ) + for c in containers_to_log: + status = self.fetch_container_logs(pod=pod, container_name=c, follow=follow_logs) + pod_logging_statuses.append(status) + return pod_logging_statuses + +
[docs] def await_container_completion(self, pod: V1Pod, container_name: str) -> None: + """ + Wait for the given container in the given pod to be completed. + + :param pod: pod spec that will be monitored + :param container_name: name of the container within the pod to monitor + """ + while True: + remote_pod = self.read_pod(pod) + terminated = container_is_completed(remote_pod, container_name) + if terminated: + break + self.log.info("Waiting for container '%s' state to be completed", container_name) + time.sleep(1)
+ +
[docs] def await_pod_completion( + self, pod: V1Pod, istio_enabled: bool = False, container_name: str = "base" + ) -> V1Pod: + """ + Monitor a pod and return the final state. + + :param istio_enabled: whether istio is enabled in the namespace + :param pod: pod spec that will be monitored + :param container_name: name of the container within the pod + :return: tuple[State, str | None] + """ + while True: + remote_pod = self.read_pod(pod) + if remote_pod.status.phase in PodPhase.terminal_states: + break + if istio_enabled and container_is_completed(remote_pod, container_name): + break + self.log.info("Pod %s has phase %s", pod.metadata.name, remote_pod.status.phase) + time.sleep(2) + return remote_pod
+ +
[docs] def parse_log_line(self, line: str) -> tuple[DateTime | None, str]: + """ + Parse K8s log line and returns the final state. + + :param line: k8s log line + :return: timestamp and log message + """ + timestamp, sep, message = line.strip().partition(" ") + if not sep: + return None, line + try: + last_log_time = cast(DateTime, pendulum.parse(timestamp)) + except ParserError: + return None, line + return last_log_time, message
+ +
[docs] def container_is_running(self, pod: V1Pod, container_name: str) -> bool: + """Read pod and checks if container is running.""" + remote_pod = self.read_pod(pod) + return container_is_running(pod=remote_pod, container_name=container_name)
+ +
[docs] def container_is_terminated(self, pod: V1Pod, container_name: str) -> bool: + """Read pod and checks if container is terminated.""" + remote_pod = self.read_pod(pod) + return container_is_terminated(pod=remote_pod, container_name=container_name)
+ + @tenacity.retry(stop=tenacity.stop_after_attempt(6), wait=tenacity.wait_exponential(max=15), reraise=True) +
[docs] def read_pod_logs( + self, + pod: V1Pod, + container_name: str, + tail_lines: int | None = None, + timestamps: bool = False, + since_seconds: int | None = None, + follow=True, + post_termination_timeout: int = 120, + **kwargs, + ) -> PodLogsConsumer: + """Read log from the POD.""" + additional_kwargs = {} + if since_seconds: + additional_kwargs["since_seconds"] = since_seconds + + if tail_lines: + additional_kwargs["tail_lines"] = tail_lines + additional_kwargs.update(**kwargs) + + try: + logs = self._client.read_namespaced_pod_log( + name=pod.metadata.name, + namespace=pod.metadata.namespace, + container=container_name, + follow=follow, + timestamps=timestamps, + _preload_content=False, + **additional_kwargs, + ) + except HTTPError: + self.log.exception("There was an error reading the kubernetes API.") + raise + + return PodLogsConsumer( + response=logs, + pod=pod, + pod_manager=self, + container_name=container_name, + post_termination_timeout=post_termination_timeout, + )
+ + @tenacity.retry(stop=tenacity.stop_after_attempt(3), wait=tenacity.wait_exponential(), reraise=True) +
[docs] def get_container_names(self, pod: V1Pod) -> list[str]: + """Return container names from the POD except for the airflow-xcom-sidecar container.""" + pod_info = self.read_pod(pod) + return [ + container_spec.name + for container_spec in pod_info.spec.containers + if container_spec.name != PodDefaults.SIDECAR_CONTAINER_NAME + ]
+ + @tenacity.retry(stop=tenacity.stop_after_attempt(3), wait=tenacity.wait_exponential(), reraise=True) +
[docs] def read_pod_events(self, pod: V1Pod) -> CoreV1EventList: + """Read events from the POD.""" + try: + return self._client.list_namespaced_event( + namespace=pod.metadata.namespace, field_selector=f"involvedObject.name={pod.metadata.name}" + ) + except HTTPError as e: + raise AirflowException(f"There was an error reading the kubernetes API: {e}")
+ + @tenacity.retry(stop=tenacity.stop_after_attempt(3), wait=tenacity.wait_exponential(), reraise=True) +
[docs] def read_pod(self, pod: V1Pod) -> V1Pod: + """Read POD information.""" + try: + return self._client.read_namespaced_pod(pod.metadata.name, pod.metadata.namespace) + except HTTPError as e: + raise AirflowException(f"There was an error reading the kubernetes API: {e}")
+ +
[docs] def await_xcom_sidecar_container_start(self, pod: V1Pod) -> None: + self.log.info("Checking if xcom sidecar container is started.") + for attempt in itertools.count(): + if self.container_is_running(pod, PodDefaults.SIDECAR_CONTAINER_NAME): + self.log.info("The xcom sidecar container is started.") + break + if not attempt: + self.log.warning("The xcom sidecar container is not yet started.") + time.sleep(1)
+ +
[docs] def extract_xcom(self, pod: V1Pod) -> str: + """Retrieve XCom value and kill xcom sidecar container.""" + try: + result = self.extract_xcom_json(pod) + return result + finally: + self.extract_xcom_kill(pod)
+ + @tenacity.retry( + stop=tenacity.stop_after_attempt(5), + wait=tenacity.wait_exponential(multiplier=1, min=4, max=10), + reraise=True, + ) +
[docs] def extract_xcom_json(self, pod: V1Pod) -> str: + """Retrieve XCom value and also check if xcom json is valid.""" + with closing( + kubernetes_stream( + self._client.connect_get_namespaced_pod_exec, + pod.metadata.name, + pod.metadata.namespace, + container=PodDefaults.SIDECAR_CONTAINER_NAME, + command=["/bin/sh"], + stdin=True, + stdout=True, + stderr=True, + tty=False, + _preload_content=False, + ) + ) as resp: + result = self._exec_pod_command( + resp, + f"if [ -s {PodDefaults.XCOM_MOUNT_PATH}/return.json ]; " + f"then cat {PodDefaults.XCOM_MOUNT_PATH}/return.json; " + f"else echo {EMPTY_XCOM_RESULT}; fi", + ) + if result and result.rstrip() != EMPTY_XCOM_RESULT: + # Note: result string is parsed to check if its valid json. + # This function still returns a string which is converted into json in the calling method. + json.loads(result) + + if result is None: + raise AirflowException(f"Failed to extract xcom from pod: {pod.metadata.name}") + return result
+ + @tenacity.retry( + stop=tenacity.stop_after_attempt(5), + wait=tenacity.wait_exponential(multiplier=1, min=4, max=10), + reraise=True, + ) +
[docs] def extract_xcom_kill(self, pod: V1Pod): + """Kill xcom sidecar container.""" + with closing( + kubernetes_stream( + self._client.connect_get_namespaced_pod_exec, + pod.metadata.name, + pod.metadata.namespace, + container=PodDefaults.SIDECAR_CONTAINER_NAME, + command=["/bin/sh"], + stdin=True, + stdout=True, + stderr=True, + tty=False, + _preload_content=False, + ) + ) as resp: + self._exec_pod_command(resp, "kill -2 1")
+ + def _exec_pod_command(self, resp, command: str) -> str | None: + res = "" + if not resp.is_open(): + return None + self.log.info("Running command... %s", command) + resp.write_stdin(f"{command}\n") + while resp.is_open(): + resp.update(timeout=1) + while resp.peek_stdout(): + res += resp.read_stdout() + error_res = "" + while resp.peek_stderr(): + error_res += resp.read_stderr() + if error_res: + self.log.info("stderr from command: %s", error_res) + break + if res: + return res + return None
+ + +
[docs]class OnFinishAction(str, enum.Enum): + """Action to take when the pod finishes.""" + +
[docs] KEEP_POD = "keep_pod"
+
[docs] DELETE_POD = "delete_pod"
+
[docs] DELETE_SUCCEEDED_POD = "delete_succeeded_pod"
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/utils/xcom_sidecar.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/utils/xcom_sidecar.html new file mode 100644 index 00000000000..3ad0d785bde --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/airflow/providers/cncf/kubernetes/utils/xcom_sidecar.html @@ -0,0 +1,927 @@ + + + + + + + + + + + + airflow.providers.cncf.kubernetes.utils.xcom_sidecar — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.cncf.kubernetes.utils.xcom_sidecar

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""Attach a sidecar container that blocks the pod from completing until Airflow pulls result data."""
+
+from __future__ import annotations
+
+import copy
+
+from kubernetes.client import models as k8s
+
+
+
[docs]class PodDefaults: + """Static defaults for Pods.""" + +
[docs] XCOM_MOUNT_PATH = "/airflow/xcom"
+
[docs] SIDECAR_CONTAINER_NAME = "airflow-xcom-sidecar"
+
[docs] XCOM_CMD = 'trap "exit 0" INT; while true; do sleep 1; done;'
+
[docs] VOLUME_MOUNT = k8s.V1VolumeMount(name="xcom", mount_path=XCOM_MOUNT_PATH)
+
[docs] VOLUME = k8s.V1Volume(name="xcom", empty_dir=k8s.V1EmptyDirVolumeSource())
+
[docs] SIDECAR_CONTAINER = k8s.V1Container( + name=SIDECAR_CONTAINER_NAME, + command=["sh", "-c", XCOM_CMD], + image="alpine", + volume_mounts=[VOLUME_MOUNT], + resources=k8s.V1ResourceRequirements( + requests={ + "cpu": "1m", + "memory": "10Mi", + }, + ), + )
+ + +
[docs]def add_xcom_sidecar( + pod: k8s.V1Pod, + *, + sidecar_container_image: str | None = None, + sidecar_container_resources: k8s.V1ResourceRequirements | dict | None = None, +) -> k8s.V1Pod: + """Add sidecar.""" + pod_cp = copy.deepcopy(pod) + pod_cp.spec.volumes = pod.spec.volumes or [] + pod_cp.spec.volumes.insert(0, PodDefaults.VOLUME) + pod_cp.spec.containers[0].volume_mounts = pod_cp.spec.containers[0].volume_mounts or [] + pod_cp.spec.containers[0].volume_mounts.insert(0, PodDefaults.VOLUME_MOUNT) + sidecar = copy.deepcopy(PodDefaults.SIDECAR_CONTAINER) + sidecar.image = sidecar_container_image or PodDefaults.SIDECAR_CONTAINER.image + if sidecar_container_resources: + sidecar.resources = sidecar_container_resources + pod_cp.spec.containers.append(sidecar) + + return pod_cp
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/index.html new file mode 100644 index 00000000000..8faeb47a73b --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/index.html @@ -0,0 +1,896 @@ + + + + + + + + + + + + Overview: module code — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

All modules for which code is available

+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes.html new file mode 100644 index 00000000000..c5cf155ac63 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes.html @@ -0,0 +1,1038 @@ + + + + + + + + + + + + tests.system.providers.cncf.kubernetes.example_kubernetes — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for tests.system.providers.cncf.kubernetes.example_kubernetes

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""
+This is an example dag for using the KubernetesPodOperator.
+"""
+
+from __future__ import annotations
+
+import os
+from datetime import datetime
+
+from kubernetes.client import models as k8s
+
+from airflow import DAG
+from airflow.operators.bash import BashOperator
+from airflow.providers.cncf.kubernetes.operators.pod import KubernetesPodOperator
+from airflow.providers.cncf.kubernetes.secret import Secret
+
+# [START howto_operator_k8s_cluster_resources]
+
[docs]secret_file = Secret("volume", "/etc/sql_conn", "airflow-secrets", "sql_alchemy_conn")
+
[docs]secret_env = Secret("env", "SQL_CONN", "airflow-secrets", "sql_alchemy_conn")
+
[docs]secret_all_keys = Secret("env", None, "airflow-secrets-2")
+
[docs]volume_mount = k8s.V1VolumeMount( + name="test-volume", mount_path="/root/mount_file", sub_path=None, read_only=True +)
+ +
[docs]configmaps = [ + k8s.V1EnvFromSource(config_map_ref=k8s.V1ConfigMapEnvSource(name="test-configmap-1")), + k8s.V1EnvFromSource(config_map_ref=k8s.V1ConfigMapEnvSource(name="test-configmap-2")), +]
+ +
[docs]volume = k8s.V1Volume( + name="test-volume", + persistent_volume_claim=k8s.V1PersistentVolumeClaimVolumeSource(claim_name="test-volume"), +)
+ +
[docs]port = k8s.V1ContainerPort(name="http", container_port=80)
+ +
[docs]init_container_volume_mounts = [ + k8s.V1VolumeMount(mount_path="/etc/foo", name="test-volume", sub_path=None, read_only=True) +]
+ +
[docs]init_environments = [k8s.V1EnvVar(name="key1", value="value1"), k8s.V1EnvVar(name="key2", value="value2")]
+ +
[docs]init_container = k8s.V1Container( + name="init-container", + image="ubuntu:16.04", + env=init_environments, + volume_mounts=init_container_volume_mounts, + command=["bash", "-cx"], + args=["echo 10"], +)
+ +
[docs]affinity = k8s.V1Affinity( + node_affinity=k8s.V1NodeAffinity( + preferred_during_scheduling_ignored_during_execution=[ + k8s.V1PreferredSchedulingTerm( + weight=1, + preference=k8s.V1NodeSelectorTerm( + match_expressions=[ + k8s.V1NodeSelectorRequirement(key="disktype", operator="In", values=["ssd"]) + ] + ), + ) + ] + ), + pod_affinity=k8s.V1PodAffinity( + required_during_scheduling_ignored_during_execution=[ + k8s.V1WeightedPodAffinityTerm( + weight=1, + pod_affinity_term=k8s.V1PodAffinityTerm( + label_selector=k8s.V1LabelSelector( + match_expressions=[ + k8s.V1LabelSelectorRequirement(key="security", operator="In", values="S1") + ] + ), + topology_key="failure-domain.beta.kubernetes.io/zone", + ), + ) + ] + ), +)
+ +
[docs]tolerations = [k8s.V1Toleration(key="key", operator="Equal", value="value")]
+ +# [END howto_operator_k8s_cluster_resources] + +
[docs]ENV_ID = os.environ.get("SYSTEM_TESTS_ENV_ID")
+
[docs]DAG_ID = "example_kubernetes_operator"
+ +with DAG( + dag_id="example_kubernetes_operator", + schedule=None, + start_date=datetime(2021, 1, 1), + tags=["example"], +) as dag: +
[docs] k = KubernetesPodOperator( + namespace="default", + image="ubuntu:16.04", + cmds=["bash", "-cx"], + arguments=["echo", "10"], + labels={"foo": "bar"}, + secrets=[secret_file, secret_env, secret_all_keys], + ports=[port], + volumes=[volume], + volume_mounts=[volume_mount], + env_from=configmaps, + name="airflow-test-pod", + task_id="task", + affinity=affinity, + on_finish_action="delete_pod", + hostnetwork=False, + tolerations=tolerations, + init_containers=[init_container], + priority_class_name="medium", + )
+ + # [START howto_operator_k8s_private_image] + quay_k8s = KubernetesPodOperator( + namespace="default", + image="quay.io/apache/bash", + image_pull_secrets=[k8s.V1LocalObjectReference("testquay")], + cmds=["bash", "-cx"], + arguments=["echo", "10", "echo pwd"], + labels={"foo": "bar"}, + name="airflow-private-image-pod", + on_finish_action="delete_pod", + in_cluster=True, + task_id="task-two", + get_logs=True, + ) + # [END howto_operator_k8s_private_image] + + # [START howto_operator_k8s_write_xcom] + write_xcom = KubernetesPodOperator( + namespace="default", + image="alpine", + cmds=["sh", "-c", "mkdir -p /airflow/xcom/;echo '[1,2,3,4]' > /airflow/xcom/return.json"], + name="write-xcom", + do_xcom_push=True, + on_finish_action="delete_pod", + in_cluster=True, + task_id="write-xcom", + get_logs=True, + ) + + pod_task_xcom_result = BashOperator( + bash_command="echo \"{{ task_instance.xcom_pull('write-xcom')[0] }}\"", + task_id="pod_task_xcom_result", + ) + + write_xcom >> pod_task_xcom_result + # [END howto_operator_k8s_write_xcom] + + from tests.system.utils.watcher import watcher + + # This test needs watcher in order to properly mark success/failure + # when "tearDown" task with trigger rule is part of the DAG + list(dag.tasks) >> watcher() + +from tests.system.utils import get_test_run # noqa: E402 + +# Needed to run the example DAG with pytest (see: tests/system/README.md#run_via_pytest) +
[docs]test_run = get_test_run(dag)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes_async.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes_async.html new file mode 100644 index 00000000000..3001b60c411 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes_async.html @@ -0,0 +1,1069 @@ + + + + + + + + + + + + tests.system.providers.cncf.kubernetes.example_kubernetes_async — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for tests.system.providers.cncf.kubernetes.example_kubernetes_async

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""
+This is an example dag for using the KubernetesPodOperator.
+"""
+
+from __future__ import annotations
+
+import os
+from datetime import datetime
+
+from kubernetes.client import models as k8s
+
+from airflow import DAG
+from airflow.operators.bash import BashOperator
+from airflow.providers.cncf.kubernetes.operators.pod import KubernetesPodOperator
+from airflow.providers.cncf.kubernetes.secret import Secret
+
+# [START howto_operator_k8s_cluster_resources]
+
[docs]secret_file = Secret("volume", "/etc/sql_conn", "airflow-secrets", "sql_alchemy_conn")
+
[docs]secret_env = Secret("env", "SQL_CONN", "airflow-secrets", "sql_alchemy_conn")
+
[docs]secret_all_keys = Secret("env", None, "airflow-secrets-2")
+
[docs]volume_mount = k8s.V1VolumeMount( + name="test-volume", mount_path="/root/mount_file", sub_path=None, read_only=True +)
+ +
[docs]configmaps = [ + k8s.V1EnvFromSource(config_map_ref=k8s.V1ConfigMapEnvSource(name="test-configmap-1")), + k8s.V1EnvFromSource(config_map_ref=k8s.V1ConfigMapEnvSource(name="test-configmap-2")), +]
+ +
[docs]volume = k8s.V1Volume( + name="test-volume", + persistent_volume_claim=k8s.V1PersistentVolumeClaimVolumeSource(claim_name="test-volume"), +)
+ +
[docs]port = k8s.V1ContainerPort(name="http", container_port=80)
+ +
[docs]init_container_volume_mounts = [ + k8s.V1VolumeMount(mount_path="/etc/foo", name="test-volume", sub_path=None, read_only=True) +]
+ +
[docs]init_environments = [k8s.V1EnvVar(name="key1", value="value1"), k8s.V1EnvVar(name="key2", value="value2")]
+ +
[docs]init_container = k8s.V1Container( + name="init-container", + image="ubuntu:16.04", + env=init_environments, + volume_mounts=init_container_volume_mounts, + command=["bash", "-cx"], + args=["echo 10"], +)
+ +
[docs]affinity = k8s.V1Affinity( + node_affinity=k8s.V1NodeAffinity( + preferred_during_scheduling_ignored_during_execution=[ + k8s.V1PreferredSchedulingTerm( + weight=1, + preference=k8s.V1NodeSelectorTerm( + match_expressions=[ + k8s.V1NodeSelectorRequirement(key="disktype", operator="In", values=["ssd"]) + ] + ), + ) + ] + ), + pod_affinity=k8s.V1PodAffinity( + required_during_scheduling_ignored_during_execution=[ + k8s.V1WeightedPodAffinityTerm( + weight=1, + pod_affinity_term=k8s.V1PodAffinityTerm( + label_selector=k8s.V1LabelSelector( + match_expressions=[ + k8s.V1LabelSelectorRequirement(key="security", operator="In", values="S1") + ] + ), + topology_key="failure-domain.beta.kubernetes.io/zone", + ), + ) + ] + ), +)
+ +
[docs]tolerations = [k8s.V1Toleration(key="key", operator="Equal", value="value")]
+ +# [END howto_operator_k8s_cluster_resources] + +
[docs]ENV_ID = os.environ.get("SYSTEM_TESTS_ENV_ID")
+
[docs]DAG_ID = "example_kubernetes_operator_async"
+ +with DAG( + dag_id=DAG_ID, + schedule=None, + start_date=datetime(2021, 1, 1), + tags=["example"], +) as dag: +
[docs] k = KubernetesPodOperator( + task_id="kubernetes_task_async", + namespace="default", + image="ubuntu:16.04", + cmds=["bash", "-cx"], + arguments=["echo", "10"], + labels={"foo": "bar"}, + secrets=[secret_file, secret_env, secret_all_keys], + ports=[port], + volumes=[volume], + volume_mounts=[volume_mount], + env_from=configmaps, + name="airflow-test-pod", + affinity=affinity, + on_finish_action="delete_pod", + hostnetwork=False, + tolerations=tolerations, + init_containers=[init_container], + priority_class_name="medium", + deferrable=True, + )
+ + # [START howto_operator_async_log] + kubernetes_task_async_log = KubernetesPodOperator( + task_id="kubernetes_task_async_log", + namespace="kubernetes_task_async_log", + in_cluster=False, + name="astro_k8s_test_pod", + image="ubuntu", + cmds=[ + "bash", + "-cx", + ( + "i=0; " + "while [ $i -ne 100 ]; " + "do i=$(($i+1)); " + "echo $i; " + "sleep 1; " + "done; " + "mkdir -p /airflow/xcom/; " + 'echo \'{"message": "good afternoon!"}\' > /airflow/xcom/return.json' + ), + ], + do_xcom_push=True, + deferrable=True, + get_logs=True, + logging_interval=5, + ) + # [END howto_operator_async_log] + + # [START howto_operator_k8s_private_image_async] + quay_k8s_async = KubernetesPodOperator( + task_id="kubernetes_private_img_task_async", + namespace="default", + image="quay.io/apache/bash", + image_pull_secrets=[k8s.V1LocalObjectReference("testquay")], + cmds=["bash", "-cx"], + arguments=["echo", "10", "echo pwd"], + labels={"foo": "bar"}, + name="airflow-private-image-pod", + on_finish_action="delete_pod", + in_cluster=True, + get_logs=True, + deferrable=True, + ) + # [END howto_operator_k8s_private_image_async] + + # [START howto_operator_k8s_write_xcom_async] + write_xcom_async = KubernetesPodOperator( + task_id="kubernetes_write_xcom_task_async", + namespace="default", + image="alpine", + cmds=["sh", "-c", "mkdir -p /airflow/xcom/;echo '[1,2,3,4]' > /airflow/xcom/return.json"], + name="write-xcom", + do_xcom_push=True, + on_finish_action="delete_pod", + in_cluster=True, + get_logs=True, + deferrable=True, + ) + + pod_task_xcom_result_async = BashOperator( + task_id="pod_task_xcom_result_async", + bash_command="echo \"{{ task_instance.xcom_pull('write-xcom')[0] }}\"", + ) + + write_xcom_async >> pod_task_xcom_result_async + # [END howto_operator_k8s_write_xcom_async] + + from tests.system.utils.watcher import watcher + + # This test needs watcher in order to properly mark success/failure + # when "tearDown" task with trigger rule is part of the DAG + list(dag.tasks) >> watcher() + +from tests.system.utils import get_test_run # noqa: E402 + +# Needed to run the example DAG with pytest (see: tests/system/README.md#run_via_pytest) +
[docs]test_run = get_test_run(dag)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes_decorator.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes_decorator.html new file mode 100644 index 00000000000..7b230d35021 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes_decorator.html @@ -0,0 +1,928 @@ + + + + + + + + + + + + tests.system.providers.cncf.kubernetes.example_kubernetes_decorator — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for tests.system.providers.cncf.kubernetes.example_kubernetes_decorator

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from datetime import datetime
+
+from airflow import DAG
+from airflow.decorators import task
+
+with DAG(
+    dag_id="example_kubernetes_decorator",
+    schedule=None,
+    start_date=datetime(2021, 1, 1),
+    tags=["example", "cncf", "kubernetes"],
+    catchup=False,
+) as dag:
+    # [START howto_operator_kubernetes]
+    @task.kubernetes(
+        image="python:3.8-slim-buster",
+        name="k8s_test",
+        namespace="default",
+        in_cluster=False,
+        config_file="/path/to/.kube/config",
+    )
+
[docs] def execute_in_k8s_pod(): + import time + + print("Hello from k8s pod") + time.sleep(2)
+ + @task.kubernetes(image="python:3.8-slim-buster", namespace="default", in_cluster=False) + def print_pattern(): + n = 5 + for i in range(n): + # inner loop to handle number of columns + # values changing acc. to outer loop + for _ in range(i + 1): + # printing stars + print("* ", end="") + + # ending line after each row + print("\r") + + execute_in_k8s_pod_instance = execute_in_k8s_pod() + print_pattern_instance = print_pattern() + + execute_in_k8s_pod_instance >> print_pattern_instance + # [END howto_operator_kubernetes] + + +from tests.system.utils import get_test_run + +# Needed to run the example DAG with pytest (see: tests/system/README.md#run_via_pytest) +
[docs]test_run = get_test_run(dag)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes_job.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes_job.html new file mode 100644 index 00000000000..22135a4d083 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes_job.html @@ -0,0 +1,965 @@ + + + + + + + + + + + + tests.system.providers.cncf.kubernetes.example_kubernetes_job — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for tests.system.providers.cncf.kubernetes.example_kubernetes_job

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""
+This is an example dag for using the KubernetesJobOperator.
+"""
+
+from __future__ import annotations
+
+import os
+from datetime import datetime
+
+from airflow import DAG
+from airflow.providers.cncf.kubernetes.operators.job import (
+    KubernetesDeleteJobOperator,
+    KubernetesJobOperator,
+    KubernetesPatchJobOperator,
+)
+
+
[docs]ENV_ID = os.environ.get("SYSTEM_TESTS_ENV_ID")
+
[docs]DAG_ID = "example_kubernetes_job_operator"
+ +
[docs]JOB_NAME = "test-pi"
+
[docs]JOB_NAMESPACE = "default"
+ +with DAG( + dag_id=DAG_ID, + schedule=None, + start_date=datetime(2021, 1, 1), + tags=["example", "kubernetes"], +) as dag: + # [START howto_operator_k8s_job] +
[docs] k8s_job = KubernetesJobOperator( + task_id="job-task", + namespace=JOB_NAMESPACE, + image="perl:5.34.0", + cmds=["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"], + name=JOB_NAME, + )
+ # [END howto_operator_k8s_job] + + # [START howto_operator_update_job] + update_job = KubernetesPatchJobOperator( + task_id="update-job-task", + namespace="default", + name=k8s_job.output["job_name"], + body={"spec": {"suspend": False}}, + ) + # [END howto_operator_update_job] + + # [START howto_operator_k8s_job_deferrable] + k8s_job_def = KubernetesJobOperator( + task_id="job-task-def", + namespace="default", + image="perl:5.34.0", + cmds=["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"], + name=JOB_NAME + "-def", + wait_until_job_complete=True, + deferrable=True, + ) + # [END howto_operator_k8s_job_deferrable] + + # [START howto_operator_delete_k8s_job] + delete_job_task = KubernetesDeleteJobOperator( + task_id="delete_job_task", + name=k8s_job.output["job_name"], + namespace=JOB_NAMESPACE, + wait_for_completion=True, + delete_on_status="Complete", + poll_interval=1.0, + ) + # [END howto_operator_delete_k8s_job] + + delete_job_task_def = KubernetesDeleteJobOperator( + task_id="delete_job_task_def", + name=k8s_job_def.output["job_name"], + namespace=JOB_NAMESPACE, + ) + + k8s_job >> update_job >> delete_job_task + k8s_job_def >> delete_job_task_def + + from tests.system.utils.watcher import watcher + + # This test needs watcher in order to properly mark success/failure + # when "tearDown" task with trigger rule is part of the DAG + list(dag.tasks) >> watcher() + +from tests.system.utils import get_test_run # noqa: E402 + +# Needed to run the example DAG with pytest (see: tests/system/README.md#run_via_pytest) +
[docs]test_run = get_test_run(dag)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes_resource.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes_resource.html new file mode 100644 index 00000000000..5f748848801 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_kubernetes_resource.html @@ -0,0 +1,943 @@ + + + + + + + + + + + + tests.system.providers.cncf.kubernetes.example_kubernetes_resource — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for tests.system.providers.cncf.kubernetes.example_kubernetes_resource

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""
+This is an example DAG which uses KubernetesCreateResourceOperator and KubernetesDeleteResourceOperator.
+In this example, we create two tasks which execute sequentially.
+The first task is to create a PVC on Kubernetes cluster.
+and the second task is to delete the PVC.
+"""
+
+from __future__ import annotations
+
+import os
+from datetime import datetime, timedelta
+
+from airflow import DAG
+from airflow.providers.cncf.kubernetes.operators.resource import (
+    KubernetesCreateResourceOperator,
+    KubernetesDeleteResourceOperator,
+)
+
+
[docs]pvc_name = "toto"
+ +
[docs]pvc_conf = f""" +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {pvc_name} +spec: + accessModes: + - ReadWriteOnce + storageClassName: standard + resources: + requests: + storage: 5Gi +"""
+ +
[docs]ENV_ID = os.environ.get("SYSTEM_TESTS_ENV_ID")
+
[docs]DAG_ID = "example_kubernetes_resource_operator"
+ +with DAG( + DAG_ID, + default_args={"max_active_runs": 1}, + description="create and delete a PVC in a kubernetes", + schedule=timedelta(days=1), + start_date=datetime(2021, 1, 1), + catchup=False, +) as dag: +
[docs] t1 = KubernetesCreateResourceOperator( + task_id="create_pvc", + yaml_conf=pvc_conf, + )
+ + t2 = KubernetesDeleteResourceOperator( + task_id="delete_pvc", + yaml_conf=pvc_conf, + ) + + t1 >> t2 + + from tests.system.utils.watcher import watcher + + # This test needs watcher in order to properly mark success/failure + # when "tearDown" task with trigger rule is part of the DAG + list(dag.tasks) >> watcher() + +from tests.system.utils import get_test_run # noqa: E402 + +# Needed to run the example DAG with pytest (see: tests/system/README.md#run_via_pytest) +
[docs]test_run = get_test_run(dag)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_spark_kubernetes.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_spark_kubernetes.html new file mode 100644 index 00000000000..de843456037 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_modules/tests/system/providers/cncf/kubernetes/example_spark_kubernetes.html @@ -0,0 +1,947 @@ + + + + + + + + + + + + tests.system.providers.cncf.kubernetes.example_spark_kubernetes — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for tests.system.providers.cncf.kubernetes.example_spark_kubernetes

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""
+This is an example DAG which uses SparkKubernetesOperator and SparkKubernetesSensor.
+In this example, we create two tasks which execute sequentially.
+The first task is to submit sparkApplication on Kubernetes cluster(the example uses spark-pi application).
+and the second task is to check the final state of the sparkApplication that submitted in the first state.
+
+Spark-on-k8s operator is required to be already installed on Kubernetes
+https://github.com/GoogleCloudPlatform/spark-on-k8s-operator
+"""
+
+from __future__ import annotations
+
+import os
+import pathlib
+from datetime import datetime, timedelta
+from os.path import join
+
+# [START import_module]
+# The DAG object; we'll need this to instantiate a DAG
+from airflow import DAG
+
+# Operators; we need this to operate!
+from airflow.providers.cncf.kubernetes.operators.spark_kubernetes import SparkKubernetesOperator
+from airflow.providers.cncf.kubernetes.sensors.spark_kubernetes import SparkKubernetesSensor
+
+# [END import_module]
+
+
+# [START instantiate_dag]
+
+
+
[docs]ENV_ID = os.environ.get("SYSTEM_TESTS_ENV_ID")
+
[docs]DAG_ID = "spark_pi"
+ +with DAG( + DAG_ID, + default_args={"max_active_runs": 1}, + description="submit spark-pi as sparkApplication on kubernetes", + schedule=timedelta(days=1), + start_date=datetime(2021, 1, 1), + catchup=False, +) as dag: + # [START SparkKubernetesOperator_DAG] +
[docs] pi_example_path = pathlib.Path(__file__).parent.resolve()
+ t1 = SparkKubernetesOperator( + task_id="spark_pi_submit", + namespace="default", + application_file=join(pi_example_path, "example_spark_kubernetes_spark_pi.yaml"), + do_xcom_push=True, + dag=dag, + ) + + t2 = SparkKubernetesSensor( + task_id="spark_pi_monitor", + namespace="default", + application_name="{{ task_instance.xcom_pull(task_ids='spark_pi_submit')['metadata']['name'] }}", + dag=dag, + ) + t1 >> t2 + + # [END SparkKubernetesOperator_DAG] + from tests.system.utils.watcher import watcher + + # This test needs watcher in order to properly mark success/failure + # when "tearDown" task with trigger rule is part of the DAG + list(dag.tasks) >> watcher() + +from tests.system.utils import get_test_run # noqa: E402 + +# Needed to run the example DAG with pytest (see: tests/system/README.md#run_via_pytest) +
[docs]test_run = get_test_run(dag)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/callbacks/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/callbacks/index.rst.txt new file mode 100644 index 00000000000..018fe4c91fb --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/callbacks/index.rst.txt @@ -0,0 +1,128 @@ +:py:mod:`airflow.providers.cncf.kubernetes.callbacks` +===================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.callbacks + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.callbacks.ExecutionMode + airflow.providers.cncf.kubernetes.callbacks.KubernetesPodOperatorCallback + + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.callbacks.client_type + + +.. py:data:: client_type + + + +.. py:class:: ExecutionMode + + + Bases: :py:obj:`str`, :py:obj:`enum.Enum` + + Enum class for execution mode. + + .. py:attribute:: SYNC + :value: 'sync' + + + + .. py:attribute:: ASYNC + :value: 'async' + + + + +.. py:class:: KubernetesPodOperatorCallback + + + `KubernetesPodOperator` callbacks methods. + + Currently, the callbacks methods are not called in the async mode, this support will be added + in the future. + + .. py:method:: on_sync_client_creation(*, client, **kwargs) + :staticmethod: + + Invoke this callback after creating the sync client. + + :param client: the created `kubernetes.client.CoreV1Api` client. + + + .. py:method:: on_pod_creation(*, pod, client, mode, **kwargs) + :staticmethod: + + Invoke this callback after creating the pod. + + :param pod: the created pod. + :param client: the Kubernetes client that can be used in the callback. + :param mode: the current execution mode, it's one of (`sync`, `async`). + + + .. py:method:: on_pod_starting(*, pod, client, mode, **kwargs) + :staticmethod: + + Invoke this callback when the pod starts. + + :param pod: the started pod. + :param client: the Kubernetes client that can be used in the callback. + :param mode: the current execution mode, it's one of (`sync`, `async`). + + + .. py:method:: on_pod_completion(*, pod, client, mode, **kwargs) + :staticmethod: + + Invoke this callback when the pod completes. + + :param pod: the completed pod. + :param client: the Kubernetes client that can be used in the callback. + :param mode: the current execution mode, it's one of (`sync`, `async`). + + + .. py:method:: on_pod_cleanup(*, pod, client, mode, **kwargs) + :staticmethod: + + Invoke this callback after cleaning/deleting the pod. + + :param pod: the completed pod. + :param client: the Kubernetes client that can be used in the callback. + :param mode: the current execution mode, it's one of (`sync`, `async`). + + + .. py:method:: on_operator_resuming(*, pod, event, client, mode, **kwargs) + :staticmethod: + + Invoke this callback when resuming the `KubernetesPodOperator` from deferred state. + + :param pod: the current state of the pod. + :param event: the returned event from the Trigger. + :param client: the Kubernetes client that can be used in the callback. + :param mode: the current execution mode, it's one of (`sync`, `async`). + + + .. py:method:: progress_callback(*, line, client, mode, **kwargs) + :staticmethod: + + Invoke this callback to process pod container logs. + + :param line: the read line of log. + :param client: the Kubernetes client that can be used in the callback. + :param mode: the current execution mode, it's one of (`sync`, `async`). + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/decorators/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/decorators/index.rst.txt new file mode 100644 index 00000000000..478efa3cc6e --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/decorators/index.rst.txt @@ -0,0 +1,15 @@ +:py:mod:`airflow.providers.cncf.kubernetes.decorators` +====================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.decorators + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + kubernetes/index.rst + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/decorators/kubernetes/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/decorators/kubernetes/index.rst.txt new file mode 100644 index 00000000000..5c83079e31c --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/decorators/kubernetes/index.rst.txt @@ -0,0 +1,33 @@ +:py:mod:`airflow.providers.cncf.kubernetes.decorators.kubernetes` +================================================================= + +.. py:module:: airflow.providers.cncf.kubernetes.decorators.kubernetes + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.decorators.kubernetes.kubernetes_task + + + +.. py:function:: kubernetes_task(python_callable = None, multiple_outputs = None, **kwargs) + + Kubernetes operator decorator. + + This wraps a function to be executed in K8s using KubernetesPodOperator. + Also accepts any argument that DockerOperator will via ``kwargs``. Can be + reused in a single DAG. + + :param python_callable: Function to decorate + :param multiple_outputs: if set, function return value will be + unrolled to multiple XCom values. Dict will unroll to xcom values with + keys as XCom keys. Defaults to False. + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/index.rst.txt new file mode 100644 index 00000000000..9b6cd816cd5 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/index.rst.txt @@ -0,0 +1,18 @@ +:py:mod:`airflow.providers.cncf.kubernetes.executors` +===================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.executors + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + kubernetes_executor/index.rst + kubernetes_executor_types/index.rst + kubernetes_executor_utils/index.rst + local_kubernetes_executor/index.rst + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor/index.rst.txt new file mode 100644 index 00000000000..f37d2dd863e --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor/index.rst.txt @@ -0,0 +1,166 @@ +:py:mod:`airflow.providers.cncf.kubernetes.executors.kubernetes_executor` +========================================================================= + +.. py:module:: airflow.providers.cncf.kubernetes.executors.kubernetes_executor + +.. autoapi-nested-parse:: + + KubernetesExecutor. + + .. seealso:: + For more information on how the KubernetesExecutor works, take a look at the guide: + :doc:`/kubernetes_executor` + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KubernetesExecutor + + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.executors.kubernetes_executor.base_version + airflow.providers.cncf.kubernetes.executors.kubernetes_executor.ARG_NAMESPACE + airflow.providers.cncf.kubernetes.executors.kubernetes_executor.ARG_MIN_PENDING_MINUTES + airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KUBERNETES_COMMANDS + + +.. py:data:: base_version + + + +.. py:data:: ARG_NAMESPACE + + + +.. py:data:: ARG_MIN_PENDING_MINUTES + + + +.. py:data:: KUBERNETES_COMMANDS + :value: () + + + +.. py:class:: KubernetesExecutor + + + Bases: :py:obj:`airflow.executors.base_executor.BaseExecutor` + + Executor for Kubernetes. + + .. py:attribute:: RUNNING_POD_LOG_LINES + :value: 100 + + + + .. py:attribute:: supports_ad_hoc_ti_run + :type: bool + :value: True + + + + .. py:method:: clear_not_launched_queued_tasks(session = NEW_SESSION) + + Clear tasks that were not yet launched, but were previously queued. + + Tasks can end up in a "Queued" state when a rescheduled/deferred operator + comes back up for execution (with the same try_number) before the + pod of its previous incarnation has been fully removed (we think). + + It's also possible when an executor abruptly shuts down (leaving a non-empty + task_queue on that executor), but that scenario is handled via normal adoption. + + This method checks each of our queued tasks to see if the corresponding pod + is around, and if not, and there's no matching entry in our own + task_queue, marks it for re-execution. + + + .. py:method:: start() + + Start the executor. + + + .. py:method:: execute_async(key, command, queue = None, executor_config = None) + + Execute task asynchronously. + + + .. py:method:: sync() + + Synchronize task state. + + + .. py:method:: get_task_log(ti, try_number) + + Return the task logs. + + :param ti: A TaskInstance object + :param try_number: current try_number to read log from + :return: tuple of logs and messages + + + .. py:method:: try_adopt_task_instances(tis) + + Try to adopt running task instances that have been abandoned by a SchedulerJob dying. + + Anything that is not adopted will be cleared by the scheduler (and then become eligible for + re-scheduling) + + :return: any TaskInstances that were unable to be adopted + + + .. py:method:: cleanup_stuck_queued_tasks(tis) + + Handle remnants of tasks that were failed because they were stuck in queued. + + Tasks can get stuck in queued. If such a task is detected, it will be marked + as `UP_FOR_RETRY` if the task instance has remaining retries or marked as `FAILED` + if it doesn't. + + :param tis: List of Task Instances to clean up + :return: List of readable task instances for a warning message + + + .. py:method:: adopt_launched_task(kube_client, pod, tis_to_flush_by_key) + + Patch existing pod so that the current KubernetesJobWatcher can monitor it via label selectors. + + :param kube_client: kubernetes client for speaking to kube API + :param pod: V1Pod spec that we will patch with new label + :param tis_to_flush_by_key: TIs that will be flushed if they aren't adopted + + + .. py:method:: end() + + Shut down the executor. + + + .. py:method:: terminate() + + Terminate the executor is not doing anything. + + + .. py:method:: get_cli_commands() + :staticmethod: + + Vends CLI commands to be included in Airflow CLI. + + Override this method to expose commands via Airflow CLI to manage this executor. This can + be commands to setup/teardown the executor, inspect state, etc. + Make sure to choose unique names for those commands, to avoid collisions. + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_types/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_types/index.rst.txt new file mode 100644 index 00000000000..c0094153af3 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_types/index.rst.txt @@ -0,0 +1,28 @@ +:py:mod:`airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types` +=============================================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types + + +Module Contents +--------------- + +.. py:data:: ADOPTED + :value: 'adopted' + + + +.. py:data:: KubernetesJobType + + + +.. py:data:: ALL_NAMESPACES + :value: 'ALL_NAMESPACES' + + + +.. py:data:: POD_EXECUTOR_DONE_KEY + :value: 'airflow_executor_done' + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_utils/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_utils/index.rst.txt new file mode 100644 index 00000000000..84f4591e5a5 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_utils/index.rst.txt @@ -0,0 +1,144 @@ +:py:mod:`airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils` +=============================================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.Singleton + airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.ResourceVersion + airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.KubernetesJobWatcher + airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.AirflowKubernetesScheduler + + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.get_base_pod_from_template + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.T + + +.. py:data:: T + + + +.. py:class:: Singleton + + + Bases: :py:obj:`type`, :py:obj:`Generic`\ [\ :py:obj:`T`\ ] + + Metaclass that allows to implement singleton pattern. + + .. py:method:: __call__(*args, **kwargs) + + Call self as a function. + + + +.. py:class:: ResourceVersion + + + Singleton for tracking resourceVersion from Kubernetes. + + .. py:attribute:: resource_version + :type: dict[str, str] + + + + +.. py:class:: KubernetesJobWatcher(namespace, watcher_queue, resource_version, scheduler_job_id, kube_config) + + + Bases: :py:obj:`multiprocessing.Process`, :py:obj:`airflow.utils.log.logging_mixin.LoggingMixin` + + Watches for Kubernetes jobs. + + .. py:method:: run() + + Perform watching. + + + .. py:method:: process_error(event) + + Process error response. + + + .. py:method:: process_status(pod_name, namespace, status, annotations, resource_version, event) + + + +.. py:class:: AirflowKubernetesScheduler(kube_config, result_queue, kube_client, scheduler_job_id) + + + Bases: :py:obj:`airflow.utils.log.logging_mixin.LoggingMixin` + + Airflow Scheduler for Kubernetes. + + .. py:method:: run_pod_async(pod, **kwargs) + + Run POD asynchronously. + + + .. py:method:: run_next(next_job) + + Receives the next job to run, builds the pod, and creates it. + + + .. py:method:: delete_pod(pod_name, namespace) + + Delete Pod from a namespace; does not raise if it does not exist. + + + .. py:method:: patch_pod_executor_done(*, pod_name, namespace) + + Add a "done" annotation to ensure we don't continually adopt pods. + + + .. py:method:: sync() + + Check the status of all currently running kubernetes jobs. + + If a job is completed, its status is placed in the result queue to be sent back to the scheduler. + + + .. py:method:: process_watcher_task(task) + + Process the task by watcher. + + + .. py:method:: terminate() + + Terminates the watcher. + + + +.. py:function:: get_base_pod_from_template(pod_template_file, kube_config) + + Get base pod from template. + + Reads either the pod_template_file set in the executor_config or the base pod_template_file + set in the airflow.cfg to craft a "base pod" that will be used by the KubernetesExecutor + + :param pod_template_file: absolute path to a pod_template_file.yaml or None + :param kube_config: The KubeConfig class generated by airflow that contains all kube metadata + :return: a V1Pod that can be used as the base pod for k8s tasks + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/local_kubernetes_executor/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/local_kubernetes_executor/index.rst.txt new file mode 100644 index 00000000000..a470b9242fe --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/executors/local_kubernetes_executor/index.rst.txt @@ -0,0 +1,195 @@ +:py:mod:`airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor` +=============================================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor + + + + +.. py:class:: LocalKubernetesExecutor(local_executor, kubernetes_executor) + + + Bases: :py:obj:`airflow.utils.log.logging_mixin.LoggingMixin` + + Chooses between LocalExecutor and KubernetesExecutor based on the queue defined on the task. + + When the task's queue is the value of ``kubernetes_queue`` in section ``[local_kubernetes_executor]`` + of the configuration (default value: `kubernetes`), KubernetesExecutor is selected to run the task, + otherwise, LocalExecutor is used. + + .. py:property:: queued_tasks + :type: dict[airflow.models.taskinstance.TaskInstanceKey, airflow.executors.base_executor.QueuedTaskInstanceType] + + Return queued tasks from local and kubernetes executor. + + + .. py:property:: running + :type: set[airflow.models.taskinstance.TaskInstanceKey] + + Return running tasks from local and kubernetes executor. + + + .. py:property:: job_id + :type: str | None + + Inherited attribute from BaseExecutor. + + Since this is not really an executor, but a wrapper of executors + we implemented it as property, so we can have custom setter. + + + .. py:property:: slots_available + :type: int + + Number of new tasks this executor instance can accept. + + + .. py:attribute:: supports_ad_hoc_ti_run + :type: bool + :value: True + + + + .. py:attribute:: supports_pickling + :type: bool + :value: False + + + + .. py:attribute:: supports_sentry + :type: bool + :value: False + + + + .. py:attribute:: is_local + :type: bool + :value: False + + + + .. py:attribute:: is_single_threaded + :type: bool + :value: False + + + + .. py:attribute:: is_production + :type: bool + :value: True + + + + .. py:attribute:: serve_logs + :type: bool + :value: True + + + + .. py:attribute:: change_sensor_mode_to_reschedule + :type: bool + :value: False + + + + .. py:attribute:: callback_sink + :type: airflow.callbacks.base_callback_sink.BaseCallbackSink | None + + + + .. py:attribute:: KUBERNETES_QUEUE + + + + .. py:method:: start() + + Start local and kubernetes executor. + + + .. py:method:: queue_command(task_instance, command, priority = 1, queue = None) + + Queues command via local or kubernetes executor. + + + .. py:method:: queue_task_instance(task_instance, mark_success = False, pickle_id = None, ignore_all_deps = False, ignore_depends_on_past = False, wait_for_past_depends_before_skipping = False, ignore_task_deps = False, ignore_ti_state = False, pool = None, cfg_path = None) + + Queues task instance via local or kubernetes executor. + + + .. py:method:: get_task_log(ti, try_number) + + Fetch task log from kubernetes executor. + + + .. py:method:: has_task(task_instance) + + Check if a task is either queued or running in either local or kubernetes executor. + + :param task_instance: TaskInstance + :return: True if the task is known to this executor + + + .. py:method:: heartbeat() + + Heartbeat sent to trigger new jobs in local and kubernetes executor. + + + .. py:method:: get_event_buffer(dag_ids = None) + + Return and flush the event buffer from local and kubernetes executor. + + :param dag_ids: dag_ids to return events for, if None returns all + :return: a dict of events + + + .. py:method:: try_adopt_task_instances(tis) + + Try to adopt running task instances that have been abandoned by a SchedulerJob dying. + + Anything that is not adopted will be cleared by the scheduler (and then become eligible for + re-scheduling) + + :return: any TaskInstances that were unable to be adopted + + + .. py:method:: cleanup_stuck_queued_tasks(tis) + + + .. py:method:: end() + + End local and kubernetes executor. + + + .. py:method:: terminate() + + Terminate local and kubernetes executor. + + + .. py:method:: debug_dump() + + Debug dump; called in response to SIGUSR2 by the scheduler. + + + .. py:method:: send_callback(request) + + Send callback for execution. + + :param request: Callback request to be executed. + + + .. py:method:: get_cli_commands() + :staticmethod: + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/hooks/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/hooks/index.rst.txt new file mode 100644 index 00000000000..d692f1494fd --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/hooks/index.rst.txt @@ -0,0 +1,15 @@ +:py:mod:`airflow.providers.cncf.kubernetes.hooks` +================================================= + +.. py:module:: airflow.providers.cncf.kubernetes.hooks + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + kubernetes/index.rst + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/hooks/kubernetes/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/hooks/kubernetes/index.rst.txt new file mode 100644 index 00000000000..a8b1ad70886 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/hooks/kubernetes/index.rst.txt @@ -0,0 +1,392 @@ +:py:mod:`airflow.providers.cncf.kubernetes.hooks.kubernetes` +============================================================ + +.. py:module:: airflow.providers.cncf.kubernetes.hooks.kubernetes + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook + airflow.providers.cncf.kubernetes.hooks.kubernetes.AsyncKubernetesHook + + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.hooks.kubernetes.LOADING_KUBE_CONFIG_FILE_RESOURCE + airflow.providers.cncf.kubernetes.hooks.kubernetes.JOB_FINAL_STATUS_CONDITION_TYPES + airflow.providers.cncf.kubernetes.hooks.kubernetes.JOB_STATUS_CONDITION_TYPES + + +.. py:data:: LOADING_KUBE_CONFIG_FILE_RESOURCE + :value: 'Loading Kubernetes configuration file kube_config from {}...' + + + +.. py:data:: JOB_FINAL_STATUS_CONDITION_TYPES + + + +.. py:data:: JOB_STATUS_CONDITION_TYPES + + + +.. py:class:: KubernetesHook(conn_id = default_conn_name, client_configuration = None, cluster_context = None, config_file = None, in_cluster = None, disable_verify_ssl = None, disable_tcp_keepalive = None) + + + Bases: :py:obj:`airflow.hooks.base.BaseHook`, :py:obj:`airflow.providers.cncf.kubernetes.utils.pod_manager.PodOperatorHookProtocol` + + Creates Kubernetes API connection. + + - use in cluster configuration by using extra field ``in_cluster`` in connection + - use custom config by providing path to the file using extra field ``kube_config_path`` in connection + - use custom configuration by providing content of kubeconfig file via + extra field ``kube_config`` in connection + - use default config by providing no extras + + This hook check for configuration option in the above order. Once an option is present it will + use this configuration. + + .. seealso:: + For more information about Kubernetes connection: + :doc:`/connections/kubernetes` + + :param conn_id: The :ref:`kubernetes connection ` + to Kubernetes cluster. + :param client_configuration: Optional dictionary of client configuration params. + Passed on to kubernetes client. + :param cluster_context: Optionally specify a context to use (e.g. if you have multiple + in your kubeconfig. + :param config_file: Path to kubeconfig file. + :param in_cluster: Set to ``True`` if running from within a kubernetes cluster. + :param disable_verify_ssl: Set to ``True`` if SSL verification should be disabled. + :param disable_tcp_keepalive: Set to ``True`` if you want to disable keepalive logic. + + .. py:property:: is_in_cluster + :type: bool + + Expose whether the hook is configured with ``load_incluster_config`` or not. + + + .. py:attribute:: conn_name_attr + :value: 'kubernetes_conn_id' + + + + .. py:attribute:: default_conn_name + :value: 'kubernetes_default' + + + + .. py:attribute:: conn_type + :value: 'kubernetes' + + + + .. py:attribute:: hook_name + :value: 'Kubernetes Cluster Connection' + + + + .. py:attribute:: DEFAULT_NAMESPACE + :value: 'default' + + + + .. py:method:: get_connection_form_widgets() + :classmethod: + + Return connection widgets to add to connection form. + + + .. py:method:: get_ui_field_behaviour() + :classmethod: + + Return custom field behaviour. + + + .. py:method:: get_connection(conn_id) + :classmethod: + + Return requested connection. + + If missing and conn_id is "kubernetes_default", will return empty connection so that hook will + default to cluster-derived credentials. + + + .. py:method:: conn_extras() + + + .. py:method:: get_conn() + + Return kubernetes api session for use with requests. + + + .. py:method:: api_client() + + Cached Kubernetes API client. + + + .. py:method:: core_v1_client() + + Get authenticated client object. + + + .. py:method:: apps_v1_client() + + + .. py:method:: custom_object_client() + + + .. py:method:: batch_v1_client() + + + .. py:method:: create_custom_object(group, version, plural, body, namespace = None) + + Create custom resource definition object in Kubernetes. + + :param group: api group + :param version: api version + :param plural: api plural + :param body: crd object definition + :param namespace: kubernetes namespace + + + .. py:method:: get_custom_object(group, version, plural, name, namespace = None) + + Get custom resource definition object from Kubernetes. + + :param group: api group + :param version: api version + :param plural: api plural + :param name: crd object name + :param namespace: kubernetes namespace + + + .. py:method:: delete_custom_object(group, version, plural, name, namespace = None, **kwargs) + + Delete custom resource definition object from Kubernetes. + + :param group: api group + :param version: api version + :param plural: api plural + :param name: crd object name + :param namespace: kubernetes namespace + + + .. py:method:: get_namespace() + + Return the namespace that defined in the connection. + + + .. py:method:: get_xcom_sidecar_container_image() + + Return the xcom sidecar image that defined in the connection. + + + .. py:method:: get_xcom_sidecar_container_resources() + + Return the xcom sidecar resources that defined in the connection. + + + .. py:method:: get_pod_log_stream(pod_name, container = '', namespace = None) + + Retrieve a log stream for a container in a kubernetes pod. + + :param pod_name: pod name + :param container: container name + :param namespace: kubernetes namespace + + + .. py:method:: get_pod_logs(pod_name, container = '', namespace = None) + + Retrieve a container's log from the specified pod. + + :param pod_name: pod name + :param container: container name + :param namespace: kubernetes namespace + + + .. py:method:: get_pod(name, namespace) + + Read pod object from kubernetes API. + + + .. py:method:: get_namespaced_pod_list(label_selector = '', namespace = None, watch = False, **kwargs) + + Retrieve a list of Kind pod which belong default kubernetes namespace. + + :param label_selector: A selector to restrict the list of returned objects by their labels + :param namespace: kubernetes namespace + :param watch: Watch for changes to the described resources and return them as a stream + + + .. py:method:: get_deployment_status(name, namespace = 'default', **kwargs) + + Get status of existing Deployment. + + :param name: Name of Deployment to retrieve + :param namespace: Deployment namespace + + + .. py:method:: create_job(job, **kwargs) + + Run Job. + + :param job: A kubernetes Job object + + + .. py:method:: get_job(job_name, namespace) + + Get Job of specified name and namespace. + + :param job_name: Name of Job to fetch. + :param namespace: Namespace of the Job. + :return: Job object + + + .. py:method:: get_job_status(job_name, namespace) + + Get job with status of specified name and namespace. + + :param job_name: Name of Job to fetch. + :param namespace: Namespace of the Job. + :return: Job object + + + .. py:method:: wait_until_job_complete(job_name, namespace, job_poll_interval = 10) + + Block job of specified name and namespace until it is complete or failed. + + :param job_name: Name of Job to fetch. + :param namespace: Namespace of the Job. + :param job_poll_interval: Interval in seconds between polling the job status + :return: Job object + + + .. py:method:: list_jobs_all_namespaces() + + Get list of Jobs from all namespaces. + + :return: V1JobList object + + + .. py:method:: list_jobs_from_namespace(namespace) + + Get list of Jobs from dedicated namespace. + + :param namespace: Namespace of the Job. + :return: V1JobList object + + + .. py:method:: is_job_complete(job) + + Check whether the given job is complete (with success or fail). + + :return: Boolean indicating that the given job is complete. + + + .. py:method:: is_job_failed(job) + :staticmethod: + + Check whether the given job is failed. + + :return: Error message if the job is failed, and False otherwise. + + + .. py:method:: is_job_successful(job) + :staticmethod: + + Check whether the given job is completed successfully.. + + :return: Error message if the job is failed, and False otherwise. + + + .. py:method:: patch_namespaced_job(job_name, namespace, body) + + Update the specified Job. + + :param job_name: name of the Job + :param namespace: the namespace to run within kubernetes + :param body: json object with parameters for update + + + +.. py:class:: AsyncKubernetesHook(*args, **kwargs) + + + Bases: :py:obj:`KubernetesHook` + + Hook to use Kubernetes SDK asynchronously. + + .. py:method:: get_conn_extras() + :async: + + + .. py:method:: get_conn() + :async: + + + .. py:method:: get_pod(name, namespace) + :async: + + Get pod's object. + + :param name: Name of the pod. + :param namespace: Name of the pod's namespace. + + + .. py:method:: delete_pod(name, namespace) + :async: + + Delete pod's object. + + :param name: Name of the pod. + :param namespace: Name of the pod's namespace. + + + .. py:method:: read_logs(name, namespace) + :async: + + Read logs inside the pod while starting containers inside. + + All the logs will be outputted with its timestamp to track + the logs after the execution of the pod is completed. The + method is used for async output of the logs only in the pod + failed it execution or the task was cancelled by the user. + + :param name: Name of the pod. + :param namespace: Name of the pod's namespace. + + + .. py:method:: get_job_status(name, namespace) + :async: + + Get job's status object. + + :param name: Name of the pod. + :param namespace: Name of the pod's namespace. + + + .. py:method:: wait_until_job_complete(name, namespace, poll_interval = 10) + :async: + + Block job of specified name and namespace until it is complete or failed. + + :param name: Name of Job to fetch. + :param namespace: Namespace of the Job. + :param poll_interval: Interval in seconds between polling the job status + :return: Job object + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/index.rst.txt new file mode 100644 index 00000000000..5f02840cd0a --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/index.rst.txt @@ -0,0 +1,51 @@ +:py:mod:`airflow.providers.cncf.kubernetes` +=========================================== + +.. py:module:: airflow.providers.cncf.kubernetes + + +Subpackages +----------- +.. toctree:: + :titlesonly: + :maxdepth: 3 + + decorators/index.rst + executors/index.rst + hooks/index.rst + kubernetes_executor_templates/index.rst + operators/index.rst + pod_template_file_examples/index.rst + resource_convert/index.rst + sensors/index.rst + triggers/index.rst + utils/index.rst + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + callbacks/index.rst + k8s_model/index.rst + kube_client/index.rst + kube_config/index.rst + kubernetes_helper_functions/index.rst + pod_generator/index.rst + pod_generator_deprecated/index.rst + pod_launcher_deprecated/index.rst + python_kubernetes_script/index.rst + secret/index.rst + template_rendering/index.rst + + +Package Contents +---------------- + +.. py:data:: __version__ + :value: '8.1.1' + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/k8s_model/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/k8s_model/index.rst.txt new file mode 100644 index 00000000000..59d05f09e36 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/k8s_model/index.rst.txt @@ -0,0 +1,66 @@ +:py:mod:`airflow.providers.cncf.kubernetes.k8s_model` +===================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.k8s_model + +.. autoapi-nested-parse:: + + Classes for interacting with Kubernetes API. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.k8s_model.K8SModel + + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.k8s_model.append_to_pod + + + +.. py:class:: K8SModel + + + Bases: :py:obj:`abc.ABC` + + Airflow Kubernetes models are here for backwards compatibility reasons only. + + Ideally clients should use the kubernetes API + and the process of + + client input -> Airflow k8s models -> k8s models + + can be avoided. All of these models implement the + `attach_to_pod` method so that they integrate with the kubernetes client. + + .. py:method:: attach_to_pod(pod) + :abstractmethod: + + Attaches to pod. + + :param pod: A pod to attach this Kubernetes object to + :return: The pod with the object attached + + + +.. py:function:: append_to_pod(pod, k8s_objects) + + Attach additional specs to an existing pod object. + + :param pod: A pod to attach a list of Kubernetes objects to + :param k8s_objects: a potential None list of K8SModels + :return: pod with the objects attached if they exist + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/kube_client/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/kube_client/index.rst.txt new file mode 100644 index 00000000000..19157fd0ee7 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/kube_client/index.rst.txt @@ -0,0 +1,52 @@ +:py:mod:`airflow.providers.cncf.kubernetes.kube_client` +======================================================= + +.. py:module:: airflow.providers.cncf.kubernetes.kube_client + +.. autoapi-nested-parse:: + + Client for kubernetes communication. + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.kube_client.get_kube_client + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.kube_client.log + airflow.providers.cncf.kubernetes.kube_client.has_kubernetes + + +.. py:data:: log + + + +.. py:data:: has_kubernetes + :value: True + + + +.. py:function:: get_kube_client(in_cluster = None, cluster_context = None, config_file = None) + + Retrieve Kubernetes client. + + :param in_cluster: whether we are in cluster + :param cluster_context: context of the cluster + :param config_file: configuration file + :return: kubernetes client + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/kube_config/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/kube_config/index.rst.txt new file mode 100644 index 00000000000..6a2dbf57d0b --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/kube_config/index.rst.txt @@ -0,0 +1,40 @@ +:py:mod:`airflow.providers.cncf.kubernetes.kube_config` +======================================================= + +.. py:module:: airflow.providers.cncf.kubernetes.kube_config + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.kube_config.KubeConfig + + + + +.. py:class:: KubeConfig + + + Configuration for Kubernetes. + + .. py:attribute:: core_section + :value: 'core' + + + + .. py:attribute:: kubernetes_section + :value: 'kubernetes_executor' + + + + .. py:attribute:: logging_section + :value: 'logging' + + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/kubernetes_executor_templates/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/kubernetes_executor_templates/index.rst.txt new file mode 100644 index 00000000000..7c68324a57a --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/kubernetes_executor_templates/index.rst.txt @@ -0,0 +1,6 @@ +:py:mod:`airflow.providers.cncf.kubernetes.kubernetes_executor_templates` +========================================================================= + +.. py:module:: airflow.providers.cncf.kubernetes.kubernetes_executor_templates + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/kubernetes_helper_functions/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/kubernetes_helper_functions/index.rst.txt new file mode 100644 index 00000000000..368f73928e3 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/kubernetes_helper_functions/index.rst.txt @@ -0,0 +1,79 @@ +:py:mod:`airflow.providers.cncf.kubernetes.kubernetes_helper_functions` +======================================================================= + +.. py:module:: airflow.providers.cncf.kubernetes.kubernetes_helper_functions + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.kubernetes_helper_functions.create_unique_id + airflow.providers.cncf.kubernetes.kubernetes_helper_functions.create_pod_id + airflow.providers.cncf.kubernetes.kubernetes_helper_functions.annotations_to_key + airflow.providers.cncf.kubernetes.kubernetes_helper_functions.get_logs_task_metadata + airflow.providers.cncf.kubernetes.kubernetes_helper_functions.annotations_for_logging_task_metadata + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.kubernetes_helper_functions.log + airflow.providers.cncf.kubernetes.kubernetes_helper_functions.alphanum_lower + airflow.providers.cncf.kubernetes.kubernetes_helper_functions.POD_NAME_MAX_LENGTH + + +.. py:data:: log + + + +.. py:data:: alphanum_lower + + + +.. py:data:: POD_NAME_MAX_LENGTH + :value: 63 + + + +.. py:function:: create_unique_id(dag_id = None, task_id = None, *, max_length = POD_NAME_MAX_LENGTH, unique = True) + + Generate unique pod or job ID given a dag_id and / or task_id. + + :param dag_id: DAG ID + :param task_id: Task ID + :param max_length: max number of characters + :param unique: whether a random string suffix should be added + :return: A valid identifier for a kubernetes pod name + + +.. py:function:: create_pod_id(dag_id = None, task_id = None, *, max_length = POD_NAME_MAX_LENGTH, unique = True) + + Generate unique pod ID given a dag_id and / or task_id. + + :param dag_id: DAG ID + :param task_id: Task ID + :param max_length: max number of characters + :param unique: whether a random string suffix should be added + :return: A valid identifier for a kubernetes pod name + + +.. py:function:: annotations_to_key(annotations) + + Build a TaskInstanceKey based on pod annotations. + + +.. py:function:: get_logs_task_metadata() + + +.. py:function:: annotations_for_logging_task_metadata(annotation_set) + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/custom_object_launcher/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/custom_object_launcher/index.rst.txt new file mode 100644 index 00000000000..b32d034c608 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/custom_object_launcher/index.rst.txt @@ -0,0 +1,149 @@ +:py:mod:`airflow.providers.cncf.kubernetes.operators.custom_object_launcher` +============================================================================ + +.. py:module:: airflow.providers.cncf.kubernetes.operators.custom_object_launcher + +.. autoapi-nested-parse:: + + Launches Custom object. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.operators.custom_object_launcher.SparkJobSpec + airflow.providers.cncf.kubernetes.operators.custom_object_launcher.KubernetesSpec + airflow.providers.cncf.kubernetes.operators.custom_object_launcher.SparkResources + airflow.providers.cncf.kubernetes.operators.custom_object_launcher.CustomObjectStatus + airflow.providers.cncf.kubernetes.operators.custom_object_launcher.CustomObjectLauncher + + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.operators.custom_object_launcher.should_retry_start_spark_job + + + +.. py:function:: should_retry_start_spark_job(exception) + + Check if an Exception indicates a transient error and warrants retrying. + + +.. py:class:: SparkJobSpec(**entries) + + + Spark job spec. + + .. py:method:: validate() + + + .. py:method:: update_resources() + + + +.. py:class:: KubernetesSpec(**entries) + + + Spark kubernetes spec. + + .. py:method:: set_attribute() + + + +.. py:class:: SparkResources(driver = None, executor = None) + + + spark resources. + + .. py:property:: resources + + Return job resources. + + + .. py:property:: driver_resources + + Return resources to use. + + + .. py:property:: executor_resources + + Return resources to use. + + + .. py:method:: convert_resources() + + + +.. py:class:: CustomObjectStatus + + + Status of the PODs. + + .. py:attribute:: SUBMITTED + :value: 'SUBMITTED' + + + + .. py:attribute:: RUNNING + :value: 'RUNNING' + + + + .. py:attribute:: FAILED + :value: 'FAILED' + + + + .. py:attribute:: SUCCEEDED + :value: 'SUCCEEDED' + + + + +.. py:class:: CustomObjectLauncher(name, namespace, kube_client, custom_obj_api, template_body = None) + + + Bases: :py:obj:`airflow.utils.log.logging_mixin.LoggingMixin` + + Launches PODS. + + .. py:method:: pod_manager() + + + .. py:method:: get_body() + + + .. py:method:: start_spark_job(image=None, code_path=None, startup_timeout = 600) + + Launch the pod synchronously and waits for completion. + + :param image: image name + :param code_path: path to the .py file for python and jar file for scala + :param startup_timeout: Timeout for startup of the pod (if pod is pending for too long, fails task) + :return: + + + .. py:method:: spark_job_not_running(spark_obj_spec) + + Test if spark_obj_spec has not started. + + + .. py:method:: check_pod_start_failure() + + + .. py:method:: delete_spark_job(spark_job_name=None) + + Delete spark job. + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/index.rst.txt new file mode 100644 index 00000000000..3caa06759da --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/index.rst.txt @@ -0,0 +1,20 @@ +:py:mod:`airflow.providers.cncf.kubernetes.operators` +===================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.operators + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + custom_object_launcher/index.rst + job/index.rst + kubernetes_pod/index.rst + pod/index.rst + resource/index.rst + spark_kubernetes/index.rst + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/job/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/job/index.rst.txt new file mode 100644 index 00000000000..e248375e1e2 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/job/index.rst.txt @@ -0,0 +1,243 @@ +:py:mod:`airflow.providers.cncf.kubernetes.operators.job` +========================================================= + +.. py:module:: airflow.providers.cncf.kubernetes.operators.job + +.. autoapi-nested-parse:: + + Executes a Kubernetes Job. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator + airflow.providers.cncf.kubernetes.operators.job.KubernetesDeleteJobOperator + airflow.providers.cncf.kubernetes.operators.job.KubernetesPatchJobOperator + + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.operators.job.log + + +.. py:data:: log + + + +.. py:class:: KubernetesJobOperator(*, job_template_file = None, full_job_spec = None, backoff_limit = None, completion_mode = None, completions = None, manual_selector = None, parallelism = None, selector = None, suspend = None, ttl_seconds_after_finished = None, wait_until_job_complete = False, job_poll_interval = 10, deferrable = conf.getboolean('operators', 'default_deferrable', fallback=False), **kwargs) + + + Bases: :py:obj:`airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator` + + Executes a Kubernetes Job. + + .. seealso:: + For more information on how to use this operator, take a look at the guide: + :ref:`howto/operator:KubernetesJobOperator` + + .. note:: + If you use `Google Kubernetes Engine `__ + and Airflow is not running in the same cluster, consider using + :class:`~airflow.providers.google.cloud.operators.kubernetes_engine.GKEStartJobOperator`, which + simplifies the authorization process. + + :param job_template_file: path to job template file (templated) + :param full_job_spec: The complete JodSpec + :param backoff_limit: Specifies the number of retries before marking this job failed. Defaults to 6 + :param completion_mode: CompletionMode specifies how Pod completions are tracked. It can be `NonIndexed` (default) or `Indexed`. + :param completions: Specifies the desired number of successfully finished pods the job should be run with. + :param manual_selector: manualSelector controls generation of pod labels and pod selectors. + :param parallelism: Specifies the maximum desired number of pods the job should run at any given time. + :param selector: The selector of this V1JobSpec. + :param suspend: Suspend specifies whether the Job controller should create Pods or not. + :param ttl_seconds_after_finished: ttlSecondsAfterFinished limits the lifetime of a Job that has finished execution (either Complete or Failed). + :param wait_until_job_complete: Whether to wait until started job finished execution (either Complete or + Failed). Default is False. + :param job_poll_interval: Interval in seconds between polling the job status. Default is 10. + Used if the parameter `wait_until_job_complete` set True. + :param deferrable: Run operator in the deferrable mode. Note that the parameter + `wait_until_job_complete` must be set True. + + .. py:attribute:: template_fields + :type: Sequence[str] + + + + .. py:method:: hook() + + + .. py:method:: client() + + + .. py:method:: create_job(job_request_obj) + + + .. py:method:: execute(context) + + Based on the deferrable parameter runs the pod asynchronously or synchronously. + + + .. py:method:: execute_deferrable() + + + .. py:method:: execute_complete(context, event, **kwargs) + + + .. py:method:: deserialize_job_template_file(path) + :staticmethod: + + Generate a Job from a file. + + Unfortunately we need access to the private method + ``_ApiClient__deserialize_model`` from the kubernetes client. + This issue is tracked here: https://github.com/kubernetes-client/python/issues/977. + + :param path: Path to the file + :return: a kubernetes.client.models.V1Job + + + .. py:method:: on_kill() + + Override this method to clean up subprocesses when a task instance gets killed. + + Any use of the threading, subprocess or multiprocessing module within an + operator needs to be cleaned up, or it will leave ghost processes behind. + + + .. py:method:: build_job_request_obj(context = None) + + Return V1Job object based on job template file, full job spec, and other operator parameters. + + The V1Job attributes are derived (in order of precedence) from operator params, full job spec, job + template file. + + + .. py:method:: reconcile_jobs(base_job, client_job) + :staticmethod: + + Merge Kubernetes Job objects. + + :param base_job: has the base attributes which are overwritten if they exist + in the client job and remain if they do not exist in the client_job + :param client_job: the job that the client wants to create. + :return: the merged jobs + + This can't be done recursively as certain fields are overwritten and some are concatenated. + + + .. py:method:: reconcile_job_specs(base_spec, client_spec) + :staticmethod: + + Merge Kubernetes JobSpec objects. + + :param base_spec: has the base attributes which are overwritten if they exist + in the client_spec and remain if they do not exist in the client_spec + :param client_spec: the spec that the client wants to create. + :return: the merged specs + + + +.. py:class:: KubernetesDeleteJobOperator(*, name, namespace, kubernetes_conn_id = KubernetesHook.default_conn_name, config_file = None, in_cluster = None, cluster_context = None, delete_on_status = None, wait_for_completion = False, poll_interval = 10.0, **kwargs) + + + Bases: :py:obj:`airflow.models.BaseOperator` + + Delete a Kubernetes Job. + + .. seealso:: + For more information on how to use this operator, take a look at the guide: + :ref:`howto/operator:KubernetesDeleteJobOperator` + + :param name: name of the Job. + :param namespace: the namespace to run within kubernetes. + :param kubernetes_conn_id: The :ref:`kubernetes connection id ` + for the Kubernetes cluster. + :param config_file: The path to the Kubernetes config file. (templated) + If not specified, default value is ``~/.kube/config`` + :param in_cluster: run kubernetes client with in_cluster configuration. + :param cluster_context: context that points to kubernetes cluster. + Ignored when in_cluster is True. If None, current-context is used. (templated) + :param delete_on_status: Condition for performing delete operation depending on the job status. Values: + ``None`` - delete the job regardless of its status, "Complete" - delete only successfully completed + jobs, "Failed" - delete only failed jobs. (default: ``None``) + :param wait_for_completion: Whether to wait for the job to complete. (default: ``False``) + :param poll_interval: Interval in seconds between polling the job status. Used when the `delete_on_status` + parameter is set. (default: 10.0) + + .. py:attribute:: template_fields + :type: Sequence[str] + :value: ('config_file', 'name', 'namespace', 'cluster_context') + + + + .. py:method:: hook() + + + .. py:method:: client() + + + .. py:method:: execute(context) + + Derive when creating an operator. + + Context is the same dictionary used as when rendering jinja templates. + + Refer to get_template_context for more context. + + + +.. py:class:: KubernetesPatchJobOperator(*, name, namespace, body, kubernetes_conn_id = KubernetesHook.default_conn_name, config_file = None, in_cluster = None, cluster_context = None, **kwargs) + + + Bases: :py:obj:`airflow.models.BaseOperator` + + Update a Kubernetes Job. + + .. seealso:: + For more information on how to use this operator, take a look at the guide: + :ref:`howto/operator:KubernetesPatchJobOperator` + + :param name: name of the Job + :param namespace: the namespace to run within kubernetes + :param body: Job json object with parameters for update + https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#job-v1-batch + e.g. ``{"spec": {"suspend": True}}`` + :param kubernetes_conn_id: The :ref:`kubernetes connection id ` + for the Kubernetes cluster. + :param config_file: The path to the Kubernetes config file. (templated) + If not specified, default value is ``~/.kube/config`` + :param in_cluster: run kubernetes client with in_cluster configuration. + :param cluster_context: context that points to kubernetes cluster. + Ignored when in_cluster is True. If None, current-context is used. (templated) + + .. py:attribute:: template_fields + :type: Sequence[str] + :value: ('config_file', 'name', 'namespace', 'body', 'cluster_context') + + + + .. py:method:: hook() + + + .. py:method:: execute(context) + + Derive when creating an operator. + + Context is the same dictionary used as when rendering jinja templates. + + Refer to get_template_context for more context. + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/kubernetes_pod/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/kubernetes_pod/index.rst.txt new file mode 100644 index 00000000000..fe91056fe2c --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/kubernetes_pod/index.rst.txt @@ -0,0 +1,11 @@ +:py:mod:`airflow.providers.cncf.kubernetes.operators.kubernetes_pod` +==================================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.operators.kubernetes_pod + +.. autoapi-nested-parse:: + + This module is deprecated. Please use :mod:`airflow.providers.cncf.kubernetes.operators.pod` instead. + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/pod/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/pod/index.rst.txt new file mode 100644 index 00000000000..62104bf5001 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/pod/index.rst.txt @@ -0,0 +1,330 @@ +:py:mod:`airflow.providers.cncf.kubernetes.operators.pod` +========================================================= + +.. py:module:: airflow.providers.cncf.kubernetes.operators.pod + +.. autoapi-nested-parse:: + + Executes task in a Kubernetes POD. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.operators.pod.PodEventType + airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator + + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.operators.pod.alphanum_lower + airflow.providers.cncf.kubernetes.operators.pod.KUBE_CONFIG_ENV_VAR + + +.. py:data:: alphanum_lower + + + +.. py:data:: KUBE_CONFIG_ENV_VAR + :value: 'KUBECONFIG' + + + +.. py:class:: PodEventType + + + Bases: :py:obj:`enum.Enum` + + Type of Events emitted by kubernetes pod. + + .. py:attribute:: WARNING + :value: 'Warning' + + + + .. py:attribute:: NORMAL + :value: 'Normal' + + + + +.. py:exception:: PodReattachFailure + + + Bases: :py:obj:`airflow.exceptions.AirflowException` + + When we expect to be able to find a pod but cannot. + + +.. py:class:: KubernetesPodOperator(*, kubernetes_conn_id = KubernetesHook.default_conn_name, namespace = None, image = None, name = None, random_name_suffix = True, cmds = None, arguments = None, ports = None, volume_mounts = None, volumes = None, env_vars = None, env_from = None, secrets = None, in_cluster = None, cluster_context = None, labels = None, reattach_on_restart = True, startup_timeout_seconds = 120, startup_check_interval_seconds = 5, get_logs = True, container_logs = BASE_CONTAINER_NAME, image_pull_policy = None, annotations = None, container_resources = None, affinity = None, config_file = None, node_selector = None, image_pull_secrets = None, service_account_name = None, hostnetwork = False, host_aliases = None, tolerations = None, security_context = None, container_security_context = None, dnspolicy = None, dns_config = None, hostname = None, subdomain = None, schedulername = None, full_pod_spec = None, init_containers = None, log_events_on_failure = False, do_xcom_push = False, pod_template_file = None, pod_template_dict = None, priority_class_name = None, pod_runtime_info_envs = None, termination_grace_period = None, configmaps = None, skip_on_exit_code = None, base_container_name = None, deferrable = conf.getboolean('operators', 'default_deferrable', fallback=False), poll_interval = 2, log_pod_spec_on_failure = True, on_finish_action = 'delete_pod', is_delete_operator_pod = None, termination_message_policy = 'File', active_deadline_seconds = None, callbacks = None, progress_callback = None, logging_interval = None, **kwargs) + + + Bases: :py:obj:`airflow.models.BaseOperator` + + Execute a task in a Kubernetes Pod. + + .. seealso:: + For more information on how to use this operator, take a look at the guide: + :ref:`howto/operator:KubernetesPodOperator` + + .. note:: + If you use `Google Kubernetes Engine `__ + and Airflow is not running in the same cluster, consider using + :class:`~airflow.providers.google.cloud.operators.kubernetes_engine.GKEStartPodOperator`, which + simplifies the authorization process. + + :param kubernetes_conn_id: The :ref:`kubernetes connection id ` + for the Kubernetes cluster. + :param namespace: the namespace to run within kubernetes. + :param image: Docker image you wish to launch. Defaults to hub.docker.com, + but fully qualified URLS will point to custom repositories. (templated) + :param name: name of the pod in which the task will run, will be used (plus a random + suffix if random_name_suffix is True) to generate a pod id (DNS-1123 subdomain, + containing only [a-z0-9.-]). + :param random_name_suffix: if True, will generate a random suffix. + :param cmds: entrypoint of the container. (templated) + The docker images's entrypoint is used if this is not provided. + :param arguments: arguments of the entrypoint. (templated) + The docker image's CMD is used if this is not provided. + :param ports: ports for the launched pod. + :param volume_mounts: volumeMounts for the launched pod. + :param volumes: volumes for the launched pod. Includes ConfigMaps and PersistentVolumes. + :param env_vars: Environment variables initialized in the container. (templated) + :param env_from: (Optional) List of sources to populate environment variables in the container. + :param secrets: Kubernetes secrets to inject in the container. + They can be exposed as environment vars or files in a volume. + :param in_cluster: run kubernetes client with in_cluster configuration. + :param cluster_context: context that points to kubernetes cluster. + Ignored when in_cluster is True. If None, current-context is used. (templated) + :param reattach_on_restart: if the worker dies while the pod is running, reattach and monitor + during the next try. If False, always create a new pod for each try. + :param labels: labels to apply to the Pod. (templated) + :param startup_timeout_seconds: timeout in seconds to startup the pod. + :param startup_check_interval_seconds: interval in seconds to check if the pod has already started + :param get_logs: get the stdout of the base container as logs of the tasks. + :param container_logs: list of containers whose logs will be published to stdout + Takes a sequence of containers, a single container name or True. If True, + all the containers logs are published. Works in conjunction with get_logs param. + The default value is the base container. + :param image_pull_policy: Specify a policy to cache or always pull an image. + :param annotations: non-identifying metadata you can attach to the Pod. + Can be a large range of data, and can include characters + that are not permitted by labels. (templated) + :param container_resources: resources for the launched pod. (templated) + :param affinity: affinity scheduling rules for the launched pod. + :param config_file: The path to the Kubernetes config file. (templated) + If not specified, default value is ``~/.kube/config`` + :param node_selector: A dict containing a group of scheduling rules. + :param image_pull_secrets: Any image pull secrets to be given to the pod. + If more than one secret is required, provide a + comma separated list: secret_a,secret_b + :param service_account_name: Name of the service account + :param hostnetwork: If True enable host networking on the pod. + :param host_aliases: A list of host aliases to apply to the containers in the pod. + :param tolerations: A list of kubernetes tolerations. + :param security_context: security options the pod should run with (PodSecurityContext). + :param container_security_context: security options the container should run with. + :param dnspolicy: dnspolicy for the pod. + :param dns_config: dns configuration (ip addresses, searches, options) for the pod. + :param hostname: hostname for the pod. + :param subdomain: subdomain for the pod. + :param schedulername: Specify a schedulername for the pod + :param full_pod_spec: The complete podSpec + :param init_containers: init container for the launched Pod + :param log_events_on_failure: Log the pod's events if a failure occurs + :param do_xcom_push: If True, the content of the file + /airflow/xcom/return.json in the container will also be pushed to an + XCom when the container completes. + :param pod_template_file: path to pod template file (templated) + :param pod_template_dict: pod template dictionary (templated) + :param priority_class_name: priority class name for the launched Pod + :param pod_runtime_info_envs: (Optional) A list of environment variables, + to be set in the container. + :param termination_grace_period: Termination grace period if task killed in UI, + defaults to kubernetes default + :param configmaps: (Optional) A list of names of config maps from which it collects ConfigMaps + to populate the environment variables with. The contents of the target + ConfigMap's Data field will represent the key-value pairs as environment variables. + Extends env_from. + :param skip_on_exit_code: If task exits with this exit code, leave the task + in ``skipped`` state (default: None). If set to ``None``, any non-zero + exit code will be treated as a failure. + :param base_container_name: The name of the base container in the pod. This container's logs + will appear as part of this task's logs if get_logs is True. Defaults to None. If None, + will consult the class variable BASE_CONTAINER_NAME (which defaults to "base") for the base + container name to use. + :param deferrable: Run operator in the deferrable mode. + :param poll_interval: Polling period in seconds to check for the status. Used only in deferrable mode. + :param log_pod_spec_on_failure: Log the pod's specification if a failure occurs + :param on_finish_action: What to do when the pod reaches its final state, or the execution is interrupted. + If "delete_pod", the pod will be deleted regardless its state; if "delete_succeeded_pod", + only succeeded pod will be deleted. You can set to "keep_pod" to keep the pod. + :param is_delete_operator_pod: What to do when the pod reaches its final + state, or the execution is interrupted. If True (default), delete the + pod; if False, leave the pod. + Deprecated - use `on_finish_action` instead. + :param termination_message_policy: The termination message policy of the base container. + Default value is "File" + :param active_deadline_seconds: The active_deadline_seconds which translates to active_deadline_seconds + in V1PodSpec. + :param callbacks: KubernetesPodOperatorCallback instance contains the callbacks methods on different step + of KubernetesPodOperator. + :param progress_callback: Callback function for receiving k8s container logs. + `progress_callback` is deprecated, please use :param `callbacks` instead. + :param logging_interval: max time in seconds that task should be in deferred state before + resuming to fetch the latest logs. If ``None``, then the task will remain in deferred state until pod + is done, and no logs will be visible until that time. + + .. py:attribute:: BASE_CONTAINER_NAME + :value: 'base' + + + + .. py:attribute:: ISTIO_CONTAINER_NAME + :value: 'istio-proxy' + + + + .. py:attribute:: KILL_ISTIO_PROXY_SUCCESS_MSG + :value: 'HTTP/1.1 200' + + + + .. py:attribute:: POD_CHECKED_KEY + :value: 'already_checked' + + + + .. py:attribute:: POST_TERMINATION_TIMEOUT + :value: 120 + + + + .. py:attribute:: template_fields + :type: Sequence[str] + :value: ('image', 'cmds', 'annotations', 'arguments', 'env_vars', 'labels', 'config_file',... + + + + .. py:attribute:: template_fields_renderers + + + + .. py:method:: pod_manager() + + + .. py:method:: hook() + + + .. py:method:: client() + + + .. py:method:: find_pod(namespace, context, *, exclude_checked = True) + + Return an already-running pod for this task instance if one exists. + + + .. py:method:: get_or_create_pod(pod_request_obj, context) + + + .. py:method:: await_pod_start(pod) + + + .. py:method:: extract_xcom(pod) + + Retrieve xcom value and kill xcom sidecar container. + + + .. py:method:: execute(context) + + Based on the deferrable parameter runs the pod asynchronously or synchronously. + + + .. py:method:: execute_sync(context) + + + .. py:method:: execute_async(context) + + + .. py:method:: invoke_defer_method(last_log_time = None) + + Redefine triggers which are being used in child classes. + + + .. py:method:: trigger_reentry(context, event) + + Point of re-entry from trigger. + + If ``logging_interval`` is None, then at this point, the pod should be done, and we'll just fetch + the logs and exit. + + If ``logging_interval`` is not None, it could be that the pod is still running, and we'll just + grab the latest logs and defer back to the trigger again. + + + .. py:method:: execute_complete(context, event, **kwargs) + + + .. py:method:: write_logs(pod, follow = False, since_time = None) + + + .. py:method:: post_complete_action(*, pod, remote_pod, **kwargs) + + Actions that must be done after operator finishes logic of the deferrable_execution. + + + .. py:method:: cleanup(pod, remote_pod) + + + .. py:method:: is_istio_enabled(pod) + + Check if istio is enabled for the namespace of the pod by inspecting the namespace labels. + + + .. py:method:: kill_istio_sidecar(pod) + + + .. py:method:: process_pod_deletion(pod, *, reraise=True) + + + .. py:method:: patch_already_checked(pod, *, reraise=True) + + Add an "already checked" annotation to ensure we don't reattach on retries. + + + .. py:method:: on_kill() + + Override this method to clean up subprocesses when a task instance gets killed. + + Any use of the threading, subprocess or multiprocessing module within an + operator needs to be cleaned up, or it will leave ghost processes behind. + + + .. py:method:: build_pod_request_obj(context = None) + + Return V1Pod object based on pod template file, full pod spec, and other operator parameters. + + The V1Pod attributes are derived (in order of precedence) from operator params, full pod spec, pod + template file. + + + .. py:method:: dry_run() + + Print out the pod definition that would be created by this operator. + + Does not include labels specific to the task instance (since there isn't + one in a dry_run) and excludes all empty elements. + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/resource/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/resource/index.rst.txt new file mode 100644 index 00000000000..e8a0293fcb6 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/resource/index.rst.txt @@ -0,0 +1,65 @@ +:py:mod:`airflow.providers.cncf.kubernetes.operators.resource` +============================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.operators.resource + +.. autoapi-nested-parse:: + + Manage a Kubernetes Resource. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.operators.resource.KubernetesCreateResourceOperator + airflow.providers.cncf.kubernetes.operators.resource.KubernetesDeleteResourceOperator + + + + +.. py:class:: KubernetesCreateResourceOperator(*, yaml_conf = None, yaml_conf_file = None, namespace = None, kubernetes_conn_id = KubernetesHook.default_conn_name, custom_resource_definition = False, namespaced = True, config_file = None, **kwargs) + + + Bases: :py:obj:`KubernetesResourceBaseOperator` + + Create a resource in a kubernetes. + + .. py:method:: create_custom_from_yaml_object(body) + + + .. py:method:: execute(context) + + Derive when creating an operator. + + Context is the same dictionary used as when rendering jinja templates. + + Refer to get_template_context for more context. + + + +.. py:class:: KubernetesDeleteResourceOperator(*, yaml_conf = None, yaml_conf_file = None, namespace = None, kubernetes_conn_id = KubernetesHook.default_conn_name, custom_resource_definition = False, namespaced = True, config_file = None, **kwargs) + + + Bases: :py:obj:`KubernetesResourceBaseOperator` + + Delete a resource in a kubernetes. + + .. py:method:: delete_custom_from_yaml_object(body) + + + .. py:method:: execute(context) + + Derive when creating an operator. + + Context is the same dictionary used as when rendering jinja templates. + + Refer to get_template_context for more context. + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/spark_kubernetes/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/spark_kubernetes/index.rst.txt new file mode 100644 index 00000000000..9a617e46ae9 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/operators/spark_kubernetes/index.rst.txt @@ -0,0 +1,139 @@ +:py:mod:`airflow.providers.cncf.kubernetes.operators.spark_kubernetes` +====================================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.operators.spark_kubernetes + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator + + + + +.. py:class:: SparkKubernetesOperator(*, image = None, code_path = None, namespace = 'default', name = 'default', application_file = None, template_spec=None, get_logs = True, do_xcom_push = False, success_run_history_limit = 1, startup_timeout_seconds=600, log_events_on_failure = False, reattach_on_restart = True, delete_on_termination = True, kubernetes_conn_id = 'kubernetes_default', **kwargs) + + + Bases: :py:obj:`airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator` + + Creates sparkApplication object in kubernetes cluster. + + .. seealso:: + For more detail about Spark Application Object have a look at the reference: + https://github.com/GoogleCloudPlatform/spark-on-k8s-operator/blob/v1beta2-1.3.3-3.1.1/docs/api-docs.md#sparkapplication + + :param application_file: filepath to kubernetes custom_resource_definition of sparkApplication + :param kubernetes_conn_id: the connection to Kubernetes cluster + :param image: Docker image you wish to launch. Defaults to hub.docker.com, + :param code_path: path to the spark code in image, + :param namespace: kubernetes namespace to put sparkApplication + :param cluster_context: context of the cluster + :param application_file: yaml file if passed + :param get_logs: get the stdout of the container as logs of the tasks. + :param do_xcom_push: If True, the content of the file + /airflow/xcom/return.json in the container will also be pushed to an + XCom when the container completes. + :param success_run_history_limit: Number of past successful runs of the application to keep. + :param delete_on_termination: What to do when the pod reaches its final + state, or the execution is interrupted. If True (default), delete the + pod; if False, leave the pod. + :param startup_timeout_seconds: timeout in seconds to startup the pod. + :param log_events_on_failure: Log the pod's events if a failure occurs + :param reattach_on_restart: if the scheduler dies while the pod is running, reattach and monitor + + .. py:property:: template_body + + Templated body for CustomObjectLauncher. + + + .. py:attribute:: template_fields + :value: ['application_file', 'namespace', 'template_spec'] + + + + .. py:attribute:: template_fields_renderers + + + + .. py:attribute:: template_ext + :value: ('yaml', 'yml', 'json') + + + + .. py:attribute:: ui_color + :value: '#f4a460' + + + + .. py:attribute:: BASE_CONTAINER_NAME + :value: 'spark-kubernetes-driver' + + + + .. py:method:: manage_template_specs() + + + .. py:method:: create_job_name() + + + .. py:method:: create_labels_for_pod(context = None, include_try_number = True) + :staticmethod: + + Generate labels for the pod to track the pod in case of Operator crash. + + :param include_try_number: add try number to labels + :param context: task context provided by airflow DAG + :return: dict. + + + .. py:method:: pod_manager() + + + .. py:method:: find_spark_job(context) + + + .. py:method:: get_or_create_spark_crd(launcher, context) + + + .. py:method:: process_pod_deletion(pod, *, reraise=True) + + + .. py:method:: hook() + + + .. py:method:: client() + + + .. py:method:: custom_obj_api() + + + .. py:method:: execute(context) + + Based on the deferrable parameter runs the pod asynchronously or synchronously. + + + .. py:method:: on_kill() + + Override this method to clean up subprocesses when a task instance gets killed. + + Any use of the threading, subprocess or multiprocessing module within an + operator needs to be cleaned up, or it will leave ghost processes behind. + + + .. py:method:: patch_already_checked(pod, *, reraise=True) + + Add an "already checked" annotation to ensure we don't reattach on retries. + + + .. py:method:: dry_run() + + Print out the spark job that would be created by this operator. + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/pod_generator/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/pod_generator/index.rst.txt new file mode 100644 index 00000000000..224ab5d7e5e --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/pod_generator/index.rst.txt @@ -0,0 +1,279 @@ +:py:mod:`airflow.providers.cncf.kubernetes.pod_generator` +========================================================= + +.. py:module:: airflow.providers.cncf.kubernetes.pod_generator + +.. autoapi-nested-parse:: + + Pod generator. + + This module provides an interface between the previous Pod + API and outputs a kubernetes.client.models.V1Pod. + The advantage being that the full Kubernetes API + is supported and no serialization need be written. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.pod_generator.PodGenerator + + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.pod_generator.make_safe_label_value + airflow.providers.cncf.kubernetes.pod_generator.datetime_to_label_safe_datestring + airflow.providers.cncf.kubernetes.pod_generator.label_safe_datestring_to_datetime + airflow.providers.cncf.kubernetes.pod_generator.merge_objects + airflow.providers.cncf.kubernetes.pod_generator.extend_object_field + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.pod_generator.log + airflow.providers.cncf.kubernetes.pod_generator.MAX_LABEL_LEN + + +.. py:data:: log + + + +.. py:data:: MAX_LABEL_LEN + :value: 63 + + + +.. py:exception:: PodMutationHookException + + + Bases: :py:obj:`airflow.exceptions.AirflowException` + + Raised when exception happens during Pod Mutation Hook execution. + + +.. py:exception:: PodReconciliationError + + + Bases: :py:obj:`airflow.exceptions.AirflowException` + + Raised when an error is encountered while trying to merge pod configs. + + +.. py:function:: make_safe_label_value(string) + + Normalize a provided label to be of valid length and characters. + + Valid label values must be 63 characters or less and must be empty or begin and + end with an alphanumeric character ([a-z0-9A-Z]) with dashes (-), underscores (_), + dots (.), and alphanumerics between. + + If the label value is greater than 63 chars once made safe, or differs in any + way from the original value sent to this function, then we need to truncate to + 53 chars, and append it with a unique hash. + + +.. py:function:: datetime_to_label_safe_datestring(datetime_obj) + + Transform a datetime string to use as a label. + + Kubernetes doesn't like ":" in labels, since ISO datetime format uses ":" but + not "_" let's + replace ":" with "_" + + :param datetime_obj: datetime.datetime object + :return: ISO-like string representing the datetime + + +.. py:function:: label_safe_datestring_to_datetime(string) + + Transform a label back to a datetime object. + + Kubernetes doesn't permit ":" in labels. ISO datetime format uses ":" but not + "_", let's + replace ":" with "_" + + :param string: str + :return: datetime.datetime object + + +.. py:class:: PodGenerator(pod = None, pod_template_file = None, extract_xcom = True) + + + Contains Kubernetes Airflow Worker configuration logic. + + Represents a kubernetes pod and manages execution of a single pod. + Any configuration that is container specific gets applied to + the first container in the list of containers. + + :param pod: The fully specified pod. Mutually exclusive with `pod_template_file` + :param pod_template_file: Path to YAML file. Mutually exclusive with `pod` + :param extract_xcom: Whether to bring up a container for xcom + + .. py:method:: gen_pod() + + Generate pod. + + + .. py:method:: add_xcom_sidecar(pod) + :staticmethod: + + Add sidecar. + + + .. py:method:: from_obj(obj) + :staticmethod: + + Convert to pod from obj. + + + .. py:method:: from_legacy_obj(obj) + :staticmethod: + + Convert to pod from obj. + + + .. py:method:: reconcile_pods(base_pod, client_pod) + :staticmethod: + + Merge Kubernetes Pod objects. + + :param base_pod: has the base attributes which are overwritten if they exist + in the client pod and remain if they do not exist in the client_pod + :param client_pod: the pod that the client wants to create. + :return: the merged pods + + This can't be done recursively as certain fields are overwritten and some are concatenated. + + + .. py:method:: reconcile_metadata(base_meta, client_meta) + :staticmethod: + + Merge Kubernetes Metadata objects. + + :param base_meta: has the base attributes which are overwritten if they exist + in the client_meta and remain if they do not exist in the client_meta + :param client_meta: the spec that the client wants to create. + :return: the merged specs + + + .. py:method:: reconcile_specs(base_spec, client_spec) + :staticmethod: + + Merge Kubernetes PodSpec objects. + + :param base_spec: has the base attributes which are overwritten if they exist + in the client_spec and remain if they do not exist in the client_spec + :param client_spec: the spec that the client wants to create. + :return: the merged specs + + + .. py:method:: reconcile_containers(base_containers, client_containers) + :staticmethod: + + Merge Kubernetes Container objects. + + :param base_containers: has the base attributes which are overwritten if they exist + in the client_containers and remain if they do not exist in the client_containers + :param client_containers: the containers that the client wants to create. + :return: the merged containers + + The runs recursively over the list of containers. + + + .. py:method:: construct_pod(dag_id, task_id, pod_id, try_number, kube_image, date, args, pod_override_object, base_worker_pod, namespace, scheduler_job_id, run_id = None, map_index = -1, *, with_mutation_hook = False) + :classmethod: + + Create a Pod. + + Construct a pod by gathering and consolidating the configuration from 3 places: + - airflow.cfg + - executor_config + - dynamic arguments + + + .. py:method:: serialize_pod(pod) + :staticmethod: + + Convert a k8s.V1Pod into a json serializable dictionary. + + :param pod: k8s.V1Pod object + :return: Serialized version of the pod returned as dict + + + .. py:method:: deserialize_model_file(path) + :staticmethod: + + Generate a Pod from a file. + + :param path: Path to the file + :return: a kubernetes.client.models.V1Pod + + + .. py:method:: deserialize_model_dict(pod_dict) + :staticmethod: + + Deserializes a Python dictionary to k8s.V1Pod. + + Unfortunately we need access to the private method + ``_ApiClient__deserialize_model`` from the kubernetes client. + This issue is tracked here; https://github.com/kubernetes-client/python/issues/977. + + :param pod_dict: Serialized dict of k8s.V1Pod object + :return: De-serialized k8s.V1Pod + + + .. py:method:: make_unique_pod_id(pod_id) + :staticmethod: + + Generate a unique Pod name. + + Kubernetes pod names must consist of one or more lowercase + rfc1035/rfc1123 labels separated by '.' with a maximum length of 253 + characters. + + Name must pass the following regex for validation + ``^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`` + + For more details, see: + https://github.com/kubernetes/kubernetes/blob/release-1.1/docs/design/identifiers.md + + :param pod_id: requested pod name + :return: ``str`` valid Pod name of appropriate length + + + +.. py:function:: merge_objects(base_obj, client_obj) + + Merge objects. + + :param base_obj: has the base attributes which are overwritten if they exist + in the client_obj and remain if they do not exist in the client_obj + :param client_obj: the object that the client wants to create. + :return: the merged objects + + +.. py:function:: extend_object_field(base_obj, client_obj, field_name) + + Add field values to existing objects. + + :param base_obj: an object which has a property `field_name` that is a list + :param client_obj: an object which has a property `field_name` that is a list. + A copy of this object is returned with `field_name` modified + :param field_name: the name of the list field + :return: the client_obj with the property `field_name` being the two properties appended + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/pod_generator_deprecated/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/pod_generator_deprecated/index.rst.txt new file mode 100644 index 00000000000..030943447e6 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/pod_generator_deprecated/index.rst.txt @@ -0,0 +1,176 @@ +:py:mod:`airflow.providers.cncf.kubernetes.pod_generator_deprecated` +==================================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.pod_generator_deprecated + +.. autoapi-nested-parse:: + + Backwards compatibility for Pod generation. + + This module provides an interface between the previous Pod + API and outputs a kubernetes.client.models.V1Pod. + The advantage being that the full Kubernetes API + is supported and no serialization need be written. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.pod_generator_deprecated.PodDefaults + airflow.providers.cncf.kubernetes.pod_generator_deprecated.PodGenerator + + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.pod_generator_deprecated.make_safe_label_value + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.pod_generator_deprecated.MAX_POD_ID_LEN + airflow.providers.cncf.kubernetes.pod_generator_deprecated.MAX_LABEL_LEN + + +.. py:data:: MAX_POD_ID_LEN + :value: 253 + + + +.. py:data:: MAX_LABEL_LEN + :value: 63 + + + +.. py:class:: PodDefaults + + + Static defaults for Pods. + + .. py:attribute:: XCOM_MOUNT_PATH + :value: '/airflow/xcom' + + + + .. py:attribute:: SIDECAR_CONTAINER_NAME + :value: 'airflow-xcom-sidecar' + + + + .. py:attribute:: XCOM_CMD + :value: 'trap "exit 0" INT; while true; do sleep 30; done;' + + + + .. py:attribute:: VOLUME_MOUNT + + + + .. py:attribute:: VOLUME + + + + .. py:attribute:: SIDECAR_CONTAINER + + + + +.. py:function:: make_safe_label_value(string) + + Normalize a provided label to be of valid length and characters. + + Valid label values must be 63 characters or less and must be empty or begin and + end with an alphanumeric character ([a-z0-9A-Z]) with dashes (-), underscores (_), + dots (.), and alphanumerics between. + + If the label value is greater than 63 chars once made safe, or differs in any + way from the original value sent to this function, then we need to truncate to + 53 chars, and append it with a unique hash. + + +.. py:class:: PodGenerator(image = None, name = None, namespace = None, volume_mounts = None, envs = None, cmds = None, args = None, labels = None, node_selectors = None, ports = None, volumes = None, image_pull_policy = None, restart_policy = None, image_pull_secrets = None, init_containers = None, service_account_name = None, resources = None, annotations = None, affinity = None, hostnetwork = False, tolerations = None, security_context = None, configmaps = None, dnspolicy = None, schedulername = None, extract_xcom = False, priority_class_name = None) + + + Contains Kubernetes Airflow Worker configuration logic. + + Represents a kubernetes pod and manages execution of a single pod. + Any configuration that is container specific gets applied to + the first container in the list of containers. + + :param image: The docker image + :param name: name in the metadata section (not the container name) + :param namespace: pod namespace + :param volume_mounts: list of kubernetes volumes mounts + :param envs: A dict containing the environment variables + :param cmds: The command to be run on the first container + :param args: The arguments to be run on the pod + :param labels: labels for the pod metadata + :param node_selectors: node selectors for the pod + :param ports: list of ports. Applies to the first container. + :param volumes: Volumes to be attached to the first container + :param image_pull_policy: Specify a policy to cache or always pull an image + :param restart_policy: The restart policy of the pod + :param image_pull_secrets: Any image pull secrets to be given to the pod. + If more than one secret is required, provide a comma separated list: + secret_a,secret_b + :param init_containers: A list of init containers + :param service_account_name: Identity for processes that run in a Pod + :param resources: Resource requirements for the first containers + :param annotations: annotations for the pod + :param affinity: A dict containing a group of affinity scheduling rules + :param hostnetwork: If True enable host networking on the pod + :param tolerations: A list of kubernetes tolerations + :param security_context: A dict containing the security context for the pod + :param configmaps: Any configmap refs to read ``configmaps`` for environments from. + If more than one configmap is required, provide a comma separated list + configmap_a,configmap_b + :param dnspolicy: Specify a dnspolicy for the pod + :param schedulername: Specify a schedulername for the pod + :param pod: The fully specified pod. Mutually exclusive with `path_or_string` + :param extract_xcom: Whether to bring up a container for xcom + :param priority_class_name: priority class name for the launched Pod + + .. py:method:: gen_pod() + + Generate pod. + + + .. py:method:: add_sidecar(pod) + :staticmethod: + + Add sidecar. + + + .. py:method:: from_obj(obj) + :staticmethod: + + Convert to pod from obj. + + + .. py:method:: make_unique_pod_id(dag_id) + :staticmethod: + + Generate a unique Pod name. + + Kubernetes pod names must be <= 253 chars and must pass the following regex for + validation + ``^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`` + + :param dag_id: a dag_id with only alphanumeric characters + :return: ``str`` valid Pod name of appropriate length + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/pod_launcher_deprecated/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/pod_launcher_deprecated/index.rst.txt new file mode 100644 index 00000000000..efcdb903142 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/pod_launcher_deprecated/index.rst.txt @@ -0,0 +1,131 @@ +:py:mod:`airflow.providers.cncf.kubernetes.pod_launcher_deprecated` +=================================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.pod_launcher_deprecated + +.. autoapi-nested-parse:: + + Launches pods. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodStatus + airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodLauncher + + + + +.. py:class:: PodStatus + + + Status of the pods. + + .. py:attribute:: PENDING + :value: 'pending' + + + + .. py:attribute:: RUNNING + :value: 'running' + + + + .. py:attribute:: FAILED + :value: 'failed' + + + + .. py:attribute:: SUCCEEDED + :value: 'succeeded' + + + + +.. py:class:: PodLauncher(kube_client = None, in_cluster = True, cluster_context = None, extract_xcom = False) + + + Bases: :py:obj:`airflow.utils.log.logging_mixin.LoggingMixin` + + Deprecated class for launching pods. + + Please use airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager instead. + + .. py:method:: run_pod_async(pod, **kwargs) + + Run pod asynchronously. + + + .. py:method:: delete_pod(pod) + + Delete pod. + + + .. py:method:: start_pod(pod, startup_timeout = 120) + + Launch the pod synchronously and wait for completion. + + :param pod: + :param startup_timeout: Timeout for startup of the pod (if pod is pending for too long, fails task) + :return: + + + .. py:method:: monitor_pod(pod, get_logs) + + Monitor a pod and return the final state. + + :param pod: pod spec that will be monitored + :param get_logs: whether to read the logs locally + + + .. py:method:: parse_log_line(line) + + Parse K8s log line and returns the final state. + + :param line: k8s log line + :return: timestamp and log message + + + .. py:method:: pod_not_started(pod) + + Test if pod has not started. + + + .. py:method:: pod_is_running(pod) + + Test if pod is running. + + + .. py:method:: base_container_is_running(pod) + + Test if base container is running. + + + .. py:method:: read_pod_logs(pod, tail_lines = None, timestamps = False, since_seconds = None) + + Read log from the pod. + + + .. py:method:: read_pod_events(pod) + + Read events from the pod. + + + .. py:method:: read_pod(pod) + + Read pod information. + + + .. py:method:: process_status(job_id, status) + + Process status information for the job. + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/pod_template_file_examples/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/pod_template_file_examples/index.rst.txt new file mode 100644 index 00000000000..7b70446728f --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/pod_template_file_examples/index.rst.txt @@ -0,0 +1,6 @@ +:py:mod:`airflow.providers.cncf.kubernetes.pod_template_file_examples` +====================================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.pod_template_file_examples + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/python_kubernetes_script/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/python_kubernetes_script/index.rst.txt new file mode 100644 index 00000000000..85b5b5da461 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/python_kubernetes_script/index.rst.txt @@ -0,0 +1,44 @@ +:py:mod:`airflow.providers.cncf.kubernetes.python_kubernetes_script` +==================================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.python_kubernetes_script + +.. autoapi-nested-parse:: + + Utilities for using the kubernetes decorator. + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.python_kubernetes_script.remove_task_decorator + airflow.providers.cncf.kubernetes.python_kubernetes_script.write_python_script + + + +.. py:function:: remove_task_decorator(python_source, task_decorator_name) + + Remove @task.kubernetes or similar as well as @setup and @teardown. + + :param python_source: python source code + :param task_decorator_name: the task decorator name + + +.. py:function:: write_python_script(jinja_context, filename, render_template_as_native_obj = False) + + Render the python script to a file to execute in the virtual environment. + + :param jinja_context: The jinja context variables to unpack and replace with its placeholders in the + template file. + :param filename: The name of the file to dump the rendered script to. + :param render_template_as_native_obj: If ``True``, rendered Jinja template would be converted + to a native Python object + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/resource_convert/configmap/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/resource_convert/configmap/index.rst.txt new file mode 100644 index 00000000000..349c61a37a5 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/resource_convert/configmap/index.rst.txt @@ -0,0 +1,36 @@ +:py:mod:`airflow.providers.cncf.kubernetes.resource_convert.configmap` +====================================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.resource_convert.configmap + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.resource_convert.configmap.convert_configmap + airflow.providers.cncf.kubernetes.resource_convert.configmap.convert_configmap_to_volume + + + +.. py:function:: convert_configmap(configmap_name) + + Convert a str into an k8s object. + + :param configmap_name: config map name + :return: + + +.. py:function:: convert_configmap_to_volume(configmap_info) + + Convert a dictionary of config_map_name and mount_path into k8s volume mount object and k8s volume. + + :param configmap_info: a dictionary of {config_map_name: mount_path} + :return: + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/resource_convert/env_variable/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/resource_convert/env_variable/index.rst.txt new file mode 100644 index 00000000000..80940349d33 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/resource_convert/env_variable/index.rst.txt @@ -0,0 +1,27 @@ +:py:mod:`airflow.providers.cncf.kubernetes.resource_convert.env_variable` +========================================================================= + +.. py:module:: airflow.providers.cncf.kubernetes.resource_convert.env_variable + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.resource_convert.env_variable.convert_env_vars + + + +.. py:function:: convert_env_vars(env_vars) + + Convert a dictionary of key:value into a list of env_vars. + + :param env_vars: + :return: + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/resource_convert/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/resource_convert/index.rst.txt new file mode 100644 index 00000000000..2da0970c991 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/resource_convert/index.rst.txt @@ -0,0 +1,17 @@ +:py:mod:`airflow.providers.cncf.kubernetes.resource_convert` +============================================================ + +.. py:module:: airflow.providers.cncf.kubernetes.resource_convert + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + configmap/index.rst + env_variable/index.rst + secret/index.rst + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/resource_convert/secret/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/resource_convert/secret/index.rst.txt new file mode 100644 index 00000000000..cc4ee842672 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/resource_convert/secret/index.rst.txt @@ -0,0 +1,36 @@ +:py:mod:`airflow.providers.cncf.kubernetes.resource_convert.secret` +=================================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.resource_convert.secret + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.resource_convert.secret.convert_secret + airflow.providers.cncf.kubernetes.resource_convert.secret.convert_image_pull_secrets + + + +.. py:function:: convert_secret(secret_name) + + Convert a str into an k8s object. + + :param secret_name: + :return: + + +.. py:function:: convert_image_pull_secrets(image_pull_secrets) + + Convert an image pull secret name into k8s local object reference. + + :param image_pull_secrets: comma separated string that contains secrets + :return: + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/secret/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/secret/index.rst.txt new file mode 100644 index 00000000000..aa768e566ce --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/secret/index.rst.txt @@ -0,0 +1,62 @@ +:py:mod:`airflow.providers.cncf.kubernetes.secret` +================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.secret + +.. autoapi-nested-parse:: + + Classes for interacting with Kubernetes API. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.secret.Secret + + + + +.. py:class:: Secret(deploy_type, deploy_target, secret, key=None, items=None) + + + Bases: :py:obj:`airflow.providers.cncf.kubernetes.k8s_model.K8SModel` + + Defines Kubernetes Secret Volume. + + .. py:method:: to_env_secret() + + Store es environment secret. + + + .. py:method:: to_env_from_secret() + + Read from environment to secret. + + + .. py:method:: to_volume_secret() + + Convert to volume secret. + + + .. py:method:: attach_to_pod(pod) + + Attach to pod. + + + .. py:method:: __eq__(other) + + Return self==value. + + + .. py:method:: __repr__() + + Return repr(self). + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/sensors/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/sensors/index.rst.txt new file mode 100644 index 00000000000..9bc189cbdec --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/sensors/index.rst.txt @@ -0,0 +1,15 @@ +:py:mod:`airflow.providers.cncf.kubernetes.sensors` +=================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.sensors + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + spark_kubernetes/index.rst + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/sensors/spark_kubernetes/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/sensors/spark_kubernetes/index.rst.txt new file mode 100644 index 00000000000..8359ea816bf --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/sensors/spark_kubernetes/index.rst.txt @@ -0,0 +1,64 @@ +:py:mod:`airflow.providers.cncf.kubernetes.sensors.spark_kubernetes` +==================================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.sensors.spark_kubernetes + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.sensors.spark_kubernetes.SparkKubernetesSensor + + + + +.. py:class:: SparkKubernetesSensor(*, application_name, attach_log = False, namespace = None, container_name = 'spark-kubernetes-driver', kubernetes_conn_id = 'kubernetes_default', api_group = 'sparkoperator.k8s.io', api_version = 'v1beta2', **kwargs) + + + Bases: :py:obj:`airflow.sensors.base.BaseSensorOperator` + + Checks sparkApplication object in kubernetes cluster. + + .. seealso:: + For more detail about Spark Application Object have a look at the reference: + https://github.com/GoogleCloudPlatform/spark-on-k8s-operator/blob/v1beta2-1.1.0-2.4.5/docs/api-docs.md#sparkapplication + + :param application_name: spark Application resource name + :param namespace: the kubernetes namespace where the sparkApplication reside in + :param container_name: the kubernetes container name where the sparkApplication reside in + :param kubernetes_conn_id: The :ref:`kubernetes connection` + to Kubernetes cluster. + :param attach_log: determines whether logs for driver pod should be appended to the sensor log + :param api_group: kubernetes api group of sparkApplication + :param api_version: kubernetes api version of sparkApplication + + .. py:attribute:: template_fields + :type: Sequence[str] + :value: ('application_name', 'namespace') + + + + .. py:attribute:: FAILURE_STATES + :value: ('FAILED', 'UNKNOWN') + + + + .. py:attribute:: SUCCESS_STATES + :value: ('COMPLETED',) + + + + .. py:method:: hook() + + + .. py:method:: poke(context) + + Override when deriving this class. + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/template_rendering/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/template_rendering/index.rst.txt new file mode 100644 index 00000000000..7532dcea04e --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/template_rendering/index.rst.txt @@ -0,0 +1,30 @@ +:py:mod:`airflow.providers.cncf.kubernetes.template_rendering` +============================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.template_rendering + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.template_rendering.render_k8s_pod_yaml + airflow.providers.cncf.kubernetes.template_rendering.get_rendered_k8s_spec + + + +.. py:function:: render_k8s_pod_yaml(task_instance) + + Render k8s pod yaml. + + +.. py:function:: get_rendered_k8s_spec(task_instance, session=NEW_SESSION) + + Fetch rendered template fields from DB. + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/triggers/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/triggers/index.rst.txt new file mode 100644 index 00000000000..fb62adfbb4d --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/triggers/index.rst.txt @@ -0,0 +1,17 @@ +:py:mod:`airflow.providers.cncf.kubernetes.triggers` +==================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.triggers + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + job/index.rst + kubernetes_pod/index.rst + pod/index.rst + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/triggers/job/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/triggers/job/index.rst.txt new file mode 100644 index 00000000000..b97080195ab --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/triggers/job/index.rst.txt @@ -0,0 +1,50 @@ +:py:mod:`airflow.providers.cncf.kubernetes.triggers.job` +======================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.triggers.job + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.triggers.job.KubernetesJobTrigger + + + + +.. py:class:: KubernetesJobTrigger(job_name, job_namespace, kubernetes_conn_id = None, poll_interval = 10.0, cluster_context = None, config_file = None, in_cluster = None) + + + Bases: :py:obj:`airflow.triggers.base.BaseTrigger` + + KubernetesJobTrigger run on the trigger worker to check the state of Job. + + :param job_name: The name of the job. + :param job_namespace: The namespace of the job. + :param kubernetes_conn_id: The :ref:`kubernetes connection id ` + for the Kubernetes cluster. + :param cluster_context: Context that points to kubernetes cluster. + :param config_file: Path to kubeconfig file. + :param poll_interval: Polling period in seconds to check for the status. + :param in_cluster: run kubernetes client with in_cluster configuration. + + .. py:method:: serialize() + + Serialize KubernetesCreateJobTrigger arguments and classpath. + + + .. py:method:: run() + :async: + + Get current job status and yield a TriggerEvent. + + + .. py:method:: hook() + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/triggers/kubernetes_pod/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/triggers/kubernetes_pod/index.rst.txt new file mode 100644 index 00000000000..50ce3db663a --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/triggers/kubernetes_pod/index.rst.txt @@ -0,0 +1,11 @@ +:py:mod:`airflow.providers.cncf.kubernetes.triggers.kubernetes_pod` +=================================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.triggers.kubernetes_pod + +.. autoapi-nested-parse:: + + This module is deprecated. Please use :mod:`airflow.providers.cncf.kubernetes.triggers.pod` instead. + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/triggers/pod/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/triggers/pod/index.rst.txt new file mode 100644 index 00000000000..2197acb727a --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/triggers/pod/index.rst.txt @@ -0,0 +1,107 @@ +:py:mod:`airflow.providers.cncf.kubernetes.triggers.pod` +======================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.triggers.pod + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.triggers.pod.ContainerState + airflow.providers.cncf.kubernetes.triggers.pod.KubernetesPodTrigger + + + + +.. py:class:: ContainerState + + + Bases: :py:obj:`str`, :py:obj:`enum.Enum` + + Possible container states. + + See https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase. + + .. py:attribute:: WAITING + :value: 'waiting' + + + + .. py:attribute:: RUNNING + :value: 'running' + + + + .. py:attribute:: TERMINATED + :value: 'terminated' + + + + .. py:attribute:: FAILED + :value: 'failed' + + + + .. py:attribute:: UNDEFINED + :value: 'undefined' + + + + +.. py:class:: KubernetesPodTrigger(pod_name, pod_namespace, trigger_start_time, base_container_name, kubernetes_conn_id = None, poll_interval = 2, cluster_context = None, config_file = None, in_cluster = None, get_logs = True, startup_timeout = 120, startup_check_interval = 5, on_finish_action = 'delete_pod', should_delete_pod = None, last_log_time = None, logging_interval = None) + + + Bases: :py:obj:`airflow.triggers.base.BaseTrigger` + + KubernetesPodTrigger run on the trigger worker to check the state of Pod. + + :param pod_name: The name of the pod. + :param pod_namespace: The namespace of the pod. + :param kubernetes_conn_id: The :ref:`kubernetes connection id ` + for the Kubernetes cluster. + :param cluster_context: Context that points to kubernetes cluster. + :param config_file: Path to kubeconfig file. + :param poll_interval: Polling period in seconds to check for the status. + :param trigger_start_time: time in Datetime format when the trigger was started + :param in_cluster: run kubernetes client with in_cluster configuration. + :param get_logs: get the stdout of the container as logs of the tasks. + :param startup_timeout: timeout in seconds to start up the pod. + :param startup_check_interval: interval in seconds to check if the pod has already started. + :param on_finish_action: What to do when the pod reaches its final state, or the execution is interrupted. + If "delete_pod", the pod will be deleted regardless its state; if "delete_succeeded_pod", + only succeeded pod will be deleted. You can set to "keep_pod" to keep the pod. + :param should_delete_pod: What to do when the pod reaches its final + state, or the execution is interrupted. If True (default), delete the + pod; if False, leave the pod. + Deprecated - use `on_finish_action` instead. + :param logging_interval: number of seconds to wait before kicking it back to + the operator to print latest logs. If ``None`` will wait until container done. + :param last_log_time: where to resume logs from + + .. py:method:: serialize() + + Serialize KubernetesCreatePodTrigger arguments and classpath. + + + .. py:method:: run() + :async: + + Get current pod status and yield a TriggerEvent. + + + .. py:method:: hook() + + + .. py:method:: define_container_state(pod) + + + .. py:method:: should_wait(pod_phase, container_state) + :staticmethod: + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/delete_from/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/delete_from/index.rst.txt new file mode 100644 index 00000000000..f66d78a2e7a --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/delete_from/index.rst.txt @@ -0,0 +1,51 @@ +:py:mod:`airflow.providers.cncf.kubernetes.utils.delete_from` +============================================================= + +.. py:module:: airflow.providers.cncf.kubernetes.utils.delete_from + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.utils.delete_from.delete_from_dict + airflow.providers.cncf.kubernetes.utils.delete_from.delete_from_yaml + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.utils.delete_from.DEFAULT_DELETION_BODY + + +.. py:data:: DEFAULT_DELETION_BODY + + + +.. py:function:: delete_from_dict(k8s_client, data, body, namespace, verbose=False, **kwargs) + + +.. py:function:: delete_from_yaml(*, k8s_client, yaml_objects=None, verbose = False, namespace = 'default', body = None, **kwargs) + + +.. py:exception:: FailToDeleteError(api_exceptions) + + + Bases: :py:obj:`Exception` + + For handling error if an error occurred when handling a yaml file during deletion of the resource. + + .. py:method:: __str__() + + Return str(self). + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/index.rst.txt new file mode 100644 index 00000000000..7c740623a7c --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/index.rst.txt @@ -0,0 +1,18 @@ +:py:mod:`airflow.providers.cncf.kubernetes.utils` +================================================= + +.. py:module:: airflow.providers.cncf.kubernetes.utils + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + delete_from/index.rst + k8s_resource_iterator/index.rst + pod_manager/index.rst + xcom_sidecar/index.rst + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/k8s_resource_iterator/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/k8s_resource_iterator/index.rst.txt new file mode 100644 index 00000000000..935b4df9121 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/k8s_resource_iterator/index.rst.txt @@ -0,0 +1,22 @@ +:py:mod:`airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator` +======================================================================= + +.. py:module:: airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator.k8s_resource_iterator + + + +.. py:function:: k8s_resource_iterator(callback, resources) + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/pod_manager/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/pod_manager/index.rst.txt new file mode 100644 index 00000000000..156cf49d053 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/pod_manager/index.rst.txt @@ -0,0 +1,333 @@ +:py:mod:`airflow.providers.cncf.kubernetes.utils.pod_manager` +============================================================= + +.. py:module:: airflow.providers.cncf.kubernetes.utils.pod_manager + +.. autoapi-nested-parse:: + + Launches PODs. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.utils.pod_manager.PodPhase + airflow.providers.cncf.kubernetes.utils.pod_manager.PodOperatorHookProtocol + airflow.providers.cncf.kubernetes.utils.pod_manager.PodLoggingStatus + airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager + airflow.providers.cncf.kubernetes.utils.pod_manager.OnFinishAction + + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.utils.pod_manager.should_retry_start_pod + airflow.providers.cncf.kubernetes.utils.pod_manager.get_container_status + airflow.providers.cncf.kubernetes.utils.pod_manager.container_is_running + airflow.providers.cncf.kubernetes.utils.pod_manager.container_is_completed + airflow.providers.cncf.kubernetes.utils.pod_manager.container_is_succeeded + airflow.providers.cncf.kubernetes.utils.pod_manager.container_is_terminated + airflow.providers.cncf.kubernetes.utils.pod_manager.get_container_termination_message + + + +.. py:exception:: PodLaunchFailedException + + + Bases: :py:obj:`airflow.exceptions.AirflowException` + + When pod launching fails in KubernetesPodOperator. + + +.. py:function:: should_retry_start_pod(exception) + + Check if an Exception indicates a transient error and warrants retrying. + + +.. py:class:: PodPhase + + + Possible pod phases. + + See https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase. + + .. py:attribute:: PENDING + :value: 'Pending' + + + + .. py:attribute:: RUNNING + :value: 'Running' + + + + .. py:attribute:: FAILED + :value: 'Failed' + + + + .. py:attribute:: SUCCEEDED + :value: 'Succeeded' + + + + .. py:attribute:: terminal_states + + + + +.. py:class:: PodOperatorHookProtocol + + + Bases: :py:obj:`Protocol` + + Protocol to define methods relied upon by KubernetesPodOperator. + + Subclasses of KubernetesPodOperator, such as GKEStartPodOperator, may use + hooks that don't extend KubernetesHook. We use this protocol to document the + methods used by KPO and ensure that these methods exist on such other hooks. + + .. py:property:: core_v1_client + :type: kubernetes.client.CoreV1Api + + Get authenticated client object. + + + .. py:property:: is_in_cluster + :type: bool + + Expose whether the hook is configured with ``load_incluster_config`` or not. + + + .. py:method:: get_pod(name, namespace) + + Read pod object from kubernetes API. + + + .. py:method:: get_namespace() + + Return the namespace that defined in the connection. + + + .. py:method:: get_xcom_sidecar_container_image() + + Return the xcom sidecar image that defined in the connection. + + + .. py:method:: get_xcom_sidecar_container_resources() + + Return the xcom sidecar resources that defined in the connection. + + + +.. py:function:: get_container_status(pod, container_name) + + Retrieve container status. + + +.. py:function:: container_is_running(pod, container_name) + + Examine V1Pod ``pod`` to determine whether ``container_name`` is running. + + If that container is present and running, returns True. Returns False otherwise. + + +.. py:function:: container_is_completed(pod, container_name) + + Examine V1Pod ``pod`` to determine whether ``container_name`` is completed. + + If that container is present and completed, returns True. Returns False otherwise. + + +.. py:function:: container_is_succeeded(pod, container_name) + + Examine V1Pod ``pod`` to determine whether ``container_name`` is completed and succeeded. + + If that container is present and completed and succeeded, returns True. Returns False otherwise. + + +.. py:function:: container_is_terminated(pod, container_name) + + Examine V1Pod ``pod`` to determine whether ``container_name`` is terminated. + + If that container is present and terminated, returns True. Returns False otherwise. + + +.. py:function:: get_container_termination_message(pod, container_name) + + +.. py:exception:: PodLaunchTimeoutException + + + Bases: :py:obj:`airflow.exceptions.AirflowException` + + When pod does not leave the ``Pending`` phase within specified timeout. + + +.. py:exception:: PodNotFoundException + + + Bases: :py:obj:`airflow.exceptions.AirflowException` + + Expected pod does not exist in kube-api. + + +.. py:class:: PodLoggingStatus + + + Return the status of the pod and last log time when exiting from `fetch_container_logs`. + + .. py:attribute:: running + :type: bool + + + + .. py:attribute:: last_log_time + :type: pendulum.DateTime | None + + + + +.. py:class:: PodManager(kube_client, callbacks = None, progress_callback = None) + + + Bases: :py:obj:`airflow.utils.log.logging_mixin.LoggingMixin` + + Create, monitor, and otherwise interact with Kubernetes pods for use with the KubernetesPodOperator. + + .. py:method:: run_pod_async(pod, **kwargs) + + Run POD asynchronously. + + + .. py:method:: delete_pod(pod) + + Delete POD. + + + .. py:method:: create_pod(pod) + + Launch the pod asynchronously. + + + .. py:method:: await_pod_start(pod, startup_timeout = 120, startup_check_interval = 1) + + Wait for the pod to reach phase other than ``Pending``. + + :param pod: + :param startup_timeout: Timeout (in seconds) for startup of the pod + (if pod is pending for too long, fails task) + :param startup_check_interval: Interval (in seconds) between checks + :return: + + + .. py:method:: follow_container_logs(pod, container_name) + + + .. py:method:: await_container_completion(pod, container_name) + + Wait for the given container in the given pod to be completed. + + :param pod: pod spec that will be monitored + :param container_name: name of the container within the pod to monitor + + + .. py:method:: await_pod_completion(pod, istio_enabled = False, container_name = 'base') + + Monitor a pod and return the final state. + + :param istio_enabled: whether istio is enabled in the namespace + :param pod: pod spec that will be monitored + :param container_name: name of the container within the pod + :return: tuple[State, str | None] + + + .. py:method:: parse_log_line(line) + + Parse K8s log line and returns the final state. + + :param line: k8s log line + :return: timestamp and log message + + + .. py:method:: container_is_running(pod, container_name) + + Read pod and checks if container is running. + + + .. py:method:: container_is_terminated(pod, container_name) + + Read pod and checks if container is terminated. + + + .. py:method:: read_pod_logs(pod, container_name, tail_lines = None, timestamps = False, since_seconds = None, follow=True, post_termination_timeout = 120, **kwargs) + + Read log from the POD. + + + .. py:method:: get_container_names(pod) + + Return container names from the POD except for the airflow-xcom-sidecar container. + + + .. py:method:: read_pod_events(pod) + + Read events from the POD. + + + .. py:method:: read_pod(pod) + + Read POD information. + + + .. py:method:: await_xcom_sidecar_container_start(pod) + + + .. py:method:: extract_xcom(pod) + + Retrieve XCom value and kill xcom sidecar container. + + + .. py:method:: extract_xcom_json(pod) + + Retrieve XCom value and also check if xcom json is valid. + + + .. py:method:: extract_xcom_kill(pod) + + Kill xcom sidecar container. + + + +.. py:class:: OnFinishAction + + + Bases: :py:obj:`str`, :py:obj:`enum.Enum` + + Action to take when the pod finishes. + + .. py:attribute:: KEEP_POD + :value: 'keep_pod' + + + + .. py:attribute:: DELETE_POD + :value: 'delete_pod' + + + + .. py:attribute:: DELETE_SUCCEEDED_POD + :value: 'delete_succeeded_pod' + + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/xcom_sidecar/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/xcom_sidecar/index.rst.txt new file mode 100644 index 00000000000..3b28dffec41 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/airflow/providers/cncf/kubernetes/utils/xcom_sidecar/index.rst.txt @@ -0,0 +1,70 @@ +:py:mod:`airflow.providers.cncf.kubernetes.utils.xcom_sidecar` +============================================================== + +.. py:module:: airflow.providers.cncf.kubernetes.utils.xcom_sidecar + +.. autoapi-nested-parse:: + + Attach a sidecar container that blocks the pod from completing until Airflow pulls result data. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.utils.xcom_sidecar.PodDefaults + + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.cncf.kubernetes.utils.xcom_sidecar.add_xcom_sidecar + + + +.. py:class:: PodDefaults + + + Static defaults for Pods. + + .. py:attribute:: XCOM_MOUNT_PATH + :value: '/airflow/xcom' + + + + .. py:attribute:: SIDECAR_CONTAINER_NAME + :value: 'airflow-xcom-sidecar' + + + + .. py:attribute:: XCOM_CMD + :value: 'trap "exit 0" INT; while true; do sleep 1; done;' + + + + .. py:attribute:: VOLUME_MOUNT + + + + .. py:attribute:: VOLUME + + + + .. py:attribute:: SIDECAR_CONTAINER + + + + +.. py:function:: add_xcom_sidecar(pod, *, sidecar_container_image = None, sidecar_container_resources = None) + + Add sidecar. + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes/index.rst.txt new file mode 100644 index 00000000000..82dcdc94fbd --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes/index.rst.txt @@ -0,0 +1,79 @@ +:py:mod:`tests.system.providers.cncf.kubernetes.example_kubernetes` +=================================================================== + +.. py:module:: tests.system.providers.cncf.kubernetes.example_kubernetes + +.. autoapi-nested-parse:: + + This is an example dag for using the KubernetesPodOperator. + + + +Module Contents +--------------- + +.. py:data:: secret_file + + + +.. py:data:: secret_env + + + +.. py:data:: secret_all_keys + + + +.. py:data:: volume_mount + + + +.. py:data:: configmaps + + + +.. py:data:: volume + + + +.. py:data:: port + + + +.. py:data:: init_container_volume_mounts + + + +.. py:data:: init_environments + + + +.. py:data:: init_container + + + +.. py:data:: affinity + + + +.. py:data:: tolerations + + + +.. py:data:: ENV_ID + + + +.. py:data:: DAG_ID + :value: 'example_kubernetes_operator' + + + +.. py:data:: k + + + +.. py:data:: test_run + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_async/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_async/index.rst.txt new file mode 100644 index 00000000000..9b1c747e4a4 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_async/index.rst.txt @@ -0,0 +1,79 @@ +:py:mod:`tests.system.providers.cncf.kubernetes.example_kubernetes_async` +========================================================================= + +.. py:module:: tests.system.providers.cncf.kubernetes.example_kubernetes_async + +.. autoapi-nested-parse:: + + This is an example dag for using the KubernetesPodOperator. + + + +Module Contents +--------------- + +.. py:data:: secret_file + + + +.. py:data:: secret_env + + + +.. py:data:: secret_all_keys + + + +.. py:data:: volume_mount + + + +.. py:data:: configmaps + + + +.. py:data:: volume + + + +.. py:data:: port + + + +.. py:data:: init_container_volume_mounts + + + +.. py:data:: init_environments + + + +.. py:data:: init_container + + + +.. py:data:: affinity + + + +.. py:data:: tolerations + + + +.. py:data:: ENV_ID + + + +.. py:data:: DAG_ID + :value: 'example_kubernetes_operator_async' + + + +.. py:data:: k + + + +.. py:data:: test_run + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_decorator/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_decorator/index.rst.txt new file mode 100644 index 00000000000..533e601caf3 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_decorator/index.rst.txt @@ -0,0 +1,34 @@ +:py:mod:`tests.system.providers.cncf.kubernetes.example_kubernetes_decorator` +============================================================================= + +.. py:module:: tests.system.providers.cncf.kubernetes.example_kubernetes_decorator + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + tests.system.providers.cncf.kubernetes.example_kubernetes_decorator.execute_in_k8s_pod + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + tests.system.providers.cncf.kubernetes.example_kubernetes_decorator.test_run + + +.. py:function:: execute_in_k8s_pod() + + +.. py:data:: test_run + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_job/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_job/index.rst.txt new file mode 100644 index 00000000000..ec7ad6fe6fc --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_job/index.rst.txt @@ -0,0 +1,41 @@ +:py:mod:`tests.system.providers.cncf.kubernetes.example_kubernetes_job` +======================================================================= + +.. py:module:: tests.system.providers.cncf.kubernetes.example_kubernetes_job + +.. autoapi-nested-parse:: + + This is an example dag for using the KubernetesJobOperator. + + + +Module Contents +--------------- + +.. py:data:: ENV_ID + + + +.. py:data:: DAG_ID + :value: 'example_kubernetes_job_operator' + + + +.. py:data:: JOB_NAME + :value: 'test-pi' + + + +.. py:data:: JOB_NAMESPACE + :value: 'default' + + + +.. py:data:: k8s_job + + + +.. py:data:: test_run + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_resource/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_resource/index.rst.txt new file mode 100644 index 00000000000..e8d12160c57 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_kubernetes_resource/index.rst.txt @@ -0,0 +1,43 @@ +:py:mod:`tests.system.providers.cncf.kubernetes.example_kubernetes_resource` +============================================================================ + +.. py:module:: tests.system.providers.cncf.kubernetes.example_kubernetes_resource + +.. autoapi-nested-parse:: + + This is an example DAG which uses KubernetesCreateResourceOperator and KubernetesDeleteResourceOperator. + In this example, we create two tasks which execute sequentially. + The first task is to create a PVC on Kubernetes cluster. + and the second task is to delete the PVC. + + + +Module Contents +--------------- + +.. py:data:: pvc_name + :value: 'toto' + + + +.. py:data:: pvc_conf + + + +.. py:data:: ENV_ID + + + +.. py:data:: DAG_ID + :value: 'example_kubernetes_resource_operator' + + + +.. py:data:: t1 + + + +.. py:data:: test_run + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_spark_kubernetes/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_spark_kubernetes/index.rst.txt new file mode 100644 index 00000000000..a33c900c472 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/example_spark_kubernetes/index.rst.txt @@ -0,0 +1,37 @@ +:py:mod:`tests.system.providers.cncf.kubernetes.example_spark_kubernetes` +========================================================================= + +.. py:module:: tests.system.providers.cncf.kubernetes.example_spark_kubernetes + +.. autoapi-nested-parse:: + + This is an example DAG which uses SparkKubernetesOperator and SparkKubernetesSensor. + In this example, we create two tasks which execute sequentially. + The first task is to submit sparkApplication on Kubernetes cluster(the example uses spark-pi application). + and the second task is to check the final state of the sparkApplication that submitted in the first state. + + Spark-on-k8s operator is required to be already installed on Kubernetes + https://github.com/GoogleCloudPlatform/spark-on-k8s-operator + + + +Module Contents +--------------- + +.. py:data:: ENV_ID + + + +.. py:data:: DAG_ID + :value: 'spark_pi' + + + +.. py:data:: pi_example_path + + + +.. py:data:: test_run + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/index.rst.txt new file mode 100644 index 00000000000..3538d6220c9 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/_api/tests/system/providers/cncf/kubernetes/index.rst.txt @@ -0,0 +1,20 @@ +:py:mod:`tests.system.providers.cncf.kubernetes` +================================================ + +.. py:module:: tests.system.providers.cncf.kubernetes + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + example_kubernetes/index.rst + example_kubernetes_async/index.rst + example_kubernetes_decorator/index.rst + example_kubernetes_job/index.rst + example_kubernetes_resource/index.rst + example_spark_kubernetes/index.rst + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/changelog.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/changelog.rst.txt new file mode 100644 index 00000000000..493abbcdb84 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/changelog.rst.txt @@ -0,0 +1,25 @@ + + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + .. NOTE! THIS FILE IS AUTOMATICALLY GENERATED AND WILL BE + OVERWRITTEN WHEN PREPARING PACKAGES. + + .. IF YOU WANT TO MODIFY THIS FILE, YOU SHOULD MODIFY THE TEMPLATE + `PROVIDER_CHANGELOG_TEMPLATE.rst.jinja2` IN the `dev/breeze/src/airflow_breeze/templates` DIRECTORY + +.. include:: ../../airflow/providers/cncf/kubernetes/CHANGELOG.rst diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/cli-ref.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/cli-ref.rst.txt new file mode 100644 index 00000000000..daa7d047f34 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/cli-ref.rst.txt @@ -0,0 +1,29 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +Kubernetes Executor Commands +============================ + +.. note:: + The CLI commands below are used from provider by Airflow 2.7.0+. + Previously they were part of the core Airflow, so if you are using Airflow below 2.7.0 look at + the core Airflow documentation for the list of CLI commands and parameters available. + +.. argparse:: + :module: airflow.providers.cncf.kubernetes.executors.kubernetes_executor + :func: _get_parser + :prog: airflow diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/commits.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/commits.rst.txt new file mode 100644 index 00000000000..702db4e2ef0 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/commits.rst.txt @@ -0,0 +1,1141 @@ + + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + .. NOTE! THIS FILE IS AUTOMATICALLY GENERATED AND WILL BE + OVERWRITTEN WHEN PREPARING PACKAGES. + + .. IF YOU WANT TO MODIFY THIS FILE, YOU SHOULD MODIFY THE TEMPLATE + `PROVIDER_COMMITS_TEMPLATE.rst.jinja2` IN the `dev/breeze/src/airflow_breeze/templates` DIRECTORY + + .. THE REMAINDER OF THE FILE IS AUTOMATICALLY GENERATED. IT WILL BE OVERWRITTEN AT RELEASE TIME! + +Package apache-airflow-providers-cncf-kubernetes +------------------------------------------------------ + +`Kubernetes `__ + + +This is detailed commit list of changes for versions provider package: ``cncf.kubernetes``. +For high-level changelog, see :doc:`package information including changelog `. + + + +8.1.1 +..... + +Latest change: 2024-04-15 + +================================================================================================= =========== ========================================= +Commit Committed Subject +================================================================================================= =========== ========================================= +`43919c2fa6 `_ 2024-04-15 ``Avoid logging empty line KPO (#38247)`` +================================================================================================= =========== ========================================= + +8.1.0 +..... + +Latest change: 2024-04-10 + +================================================================================================= =========== =================================================================================================== +Commit Committed Subject +================================================================================================= =========== =================================================================================================== +`5fa80b6aea `_ 2024-04-10 ``Prepare docs 1st wave (RC1) April 2024 (#38863)`` +`78f84b9147 `_ 2024-04-09 ``fix: try002 for provider cncf kubernetes (#38799)`` +`a19a9cb523 `_ 2024-04-05 ``removed usage of deprecated function for naming the pod in provider k8s pod.py (#38638)`` +`ab5aabe50b `_ 2024-04-02 ``Implement delete_on_status parameter for KubernetesDeleteJobOperator (#38458)`` +`ec6091d498 `_ 2024-03-31 ``Fix spark operator log retrieval from driver (#38106)`` +`afb686c95e `_ 2024-03-26 ``Implement deferrable mode for GKEStartJobOperator (#38454)`` +`a3f7ddd465 `_ 2024-03-26 ``KPO Add follow log in termination step (#38081)`` +`32ed83bd0e `_ 2024-03-25 ``Refactor GKE hooks (#38404)`` +`fc868f4be2 `_ 2024-03-22 ``Implement deferrable mode for KubernetesJobOperator (#38251)`` +`1a9b71a129 `_ 2024-03-21 ``Create KubernetesPatchJobOperator operator (#38146)`` +`29ac05f496 `_ 2024-03-18 ``Create DeleteKubernetesJobOperator and GKEDeleteJobOperator operators (#37793)`` +`b5b972a106 `_ 2024-03-18 ``Update yanked versions in providers changelogs (#38262)`` +`d4350a6bed `_ 2024-03-18 ``Fix dynamic allocation specs handling for custom launcher (#38223)`` +`0a74928894 `_ 2024-03-18 ``Bump ruff to 0.3.3 (#38240)`` +`f3982aa2a4 `_ 2024-03-18 ``Use startup_check_interval_seconds instead of poll_interval to check pod while startup (#38075)`` +`c32d41d94d `_ 2024-03-18 ``Implement wait_until_job_complete parameter for KubernetesJobOperator (#37998)`` +`1d3010c4ab `_ 2024-03-12 ``Fix case if 'SparkKubernetesOperator.application_file' is templated file (#38035)`` +`8f773a62c1 `_ 2024-03-08 ``Add GKECreateCustomResourceOperator and GKEDeleteCustomResourceOperator operators (#37616)`` +`a7b7928a2a `_ 2024-03-07 ``fix: reduce irrelevant error logs for pod events. (#37944)`` +`8e6f78a735 `_ 2024-03-06 ``Use SIGINT signal number instead of signal name (#37905)`` +`ca72f0fd89 `_ 2024-03-06 ``Add GKEListJobsOperator and GKEDescribeJobOperator (#37598)`` +================================================================================================= =========== =================================================================================================== + +8.0.1 +..... + +Latest change: 2024-03-04 + +================================================================================================= =========== =========================================================================================== +Commit Committed Subject +================================================================================================= =========== =========================================================================================== +`83316b8158 `_ 2024-03-04 ``Prepare docs 1st wave (RC1) March 2024 (#37876)`` +`30f7b2abe6 `_ 2024-03-04 ``Avoid to use too broad 'noqa' (#37862)`` +`d470674912 `_ 2024-03-01 ``Immediately fail the task in case of worker pod having a fatal container state (#37670)`` +`77341ef6a1 `_ 2024-02-29 ``Avoid non-recommended usage of logging (#37792)`` +`cd33c2a6a7 `_ 2024-02-27 ``Migrate executor docs to respective providers (#37728)`` +`c6ba13adf2 `_ 2024-02-26 ``Skip pod cleanup in case of pod creation failed (#37671)`` +================================================================================================= =========== =========================================================================================== + +8.0.0 +..... + +Latest change: 2024-02-19 + +================================================================================================= =========== ============================================================================================================== +Commit Committed Subject +================================================================================================= =========== ============================================================================================================== +`fa234e0d22 `_ 2024-02-19 ``Prepare docs 1st wave (RC3) of Providers February 2024 (#37521)`` +`6412b06a7b `_ 2024-02-18 ``Fix KPO task hanging when pod fails to start within specified timeout (#37514)`` +`d50a25bd35 `_ 2024-02-17 ``Fix KeyError when KPO exits too soon (#37508)`` +`75182363a2 `_ 2024-02-17 ``Prepare docs 1st wave (RC2) of Providers February 2024 (#37471)`` +`5a0be392e6 `_ 2024-02-16 ``Add comment about versions updated by release manager (#37488)`` +`c84efe77a5 `_ 2024-02-15 ``KPO Maintain backward compatibility for execute_complete and trigger run method (#37454)`` +`32ba99b6c2 `_ 2024-02-15 ``Create GKEStartJobOperator and KubernetesJobOperator (#36847)`` +`0be6430938 `_ 2024-02-15 ``Revert "KPO Maintain backward compatibility for execute_complete and trigger run method (#37363)" (#37446)`` +`df132b2dd6 `_ 2024-02-15 ``Add GKEStartKueueInsideClusterOperator (#37072)`` +`0640e6d595 `_ 2024-02-14 ``KPO Maintain backward compatibility for execute_complete and trigger run method (#37363)`` +`34c06c6922 `_ 2024-02-14 ``Convert Kubernetes ApiException status code to string to ensure it's correctly checked (#37405)`` +`bfb054e9e8 `_ 2024-02-12 ``Prepare docs 1st wave of Providers February 2024 (#37326)`` +`053485ba56 `_ 2024-02-12 ``Modify KPO to log container log periodically (#37279)`` +`f689c3f606 `_ 2024-02-12 ``Add d401 support to kubernetes provider (#37301)`` +`6246eec96f `_ 2024-02-10 ``Fix occasional attr-undefined for the python_kubernetes_script (#37318)`` +`e99487946a `_ 2024-02-10 ``The task is stuck in a queued state forever in case of pod launch errors (#36882)`` +`9a529a8d43 `_ 2024-02-10 ``Fix hanging KPO on deferrable task with do_xcom_push (#37300)`` +`f691adf710 `_ 2024-02-09 ``Fix rendering 'SparkKubernetesOperator.template_body' (#37271)`` +`7932958488 `_ 2024-02-05 ``Fix assignment of template field in '__init__' in 'KubernetesPodOperator' (#37010)`` +`dec2662190 `_ 2024-01-30 ``feat: Switch all class, functions, methods deprecations to decorators (#36876)`` +`c36c4db3f7 `_ 2024-01-29 ``Kubernetes version bump (#37040)`` +================================================================================================= =========== ============================================================================================================== + +7.14.0 +...... + +Latest change: 2024-01-26 + +================================================================================================= =========== ====================================================================================== +Commit Committed Subject +================================================================================================= =========== ====================================================================================== +`cead3da4a6 `_ 2024-01-26 ``Add docs for RC2 wave of providers for 2nd round of Jan 2024 (#37019)`` +`dd627d7f46 `_ 2024-01-26 ``36888-Fix k8 configmap issue in 7.14.0rc1 (#37001)`` +`d78a114aa0 `_ 2024-01-23 ``Increase tenacity wait in read_pod_logs (#36955)`` +`2b4da0101f `_ 2024-01-22 ``Prepare docs 2nd wave of Providers January 2024 (#36945)`` +`43d192543e `_ 2024-01-20 ``Template field support for configmaps in the KubernetesPodOperator (#36922)`` +`6dc53524a5 `_ 2024-01-20 ``Create a generic callbacks class for KubernetesPodOperator (#35714)`` +`d3b4a91135 `_ 2024-01-20 ``fix: Avoid retrying after KubernetesPodOperator has been marked as failed (#36749)`` +`6ff96af480 `_ 2024-01-18 ``Fix stacklevel in warnings.warn into the providers (#36831)`` +`142f08abb5 `_ 2024-01-12 ``Change field type for kube_config (#36752)`` +`aa25affec6 `_ 2024-01-12 ``Add SparkKubernetesOperator crd implementation (#22253)`` +`2ffa6e4c4c `_ 2024-01-12 ``Add support of Pendulum 3 (#36281)`` +`19ebcac239 `_ 2024-01-07 ``Prepare docs 1st wave of Providers January 2024 (#36640)`` +`2f15c95a28 `_ 2024-01-03 ``Changing wording in docstring for CNCF provider (#36547)`` +`6937ae7647 `_ 2023-12-30 ``Speed up autocompletion of Breeze by simplifying provider state (#36499)`` +================================================================================================= =========== ====================================================================================== + +7.13.0 +...... + +Latest change: 2023-12-28 + +================================================================================================= =========== ========================================================================================================== +Commit Committed Subject +================================================================================================= =========== ========================================================================================================== +`9b5d6bfe27 `_ 2023-12-28 ``Add documentation for 3rd wave of providers in Deember (#36464)`` +`2bd60771a8 `_ 2023-12-26 ``Remove deprecated input parameters in the k8s pod operator (#36433)`` +`a7700c1567 `_ 2023-12-26 ``Add reminder about update stub file in case of change KubernetesPodOperator's arguments (#36434)`` +`ee219e658d `_ 2023-12-26 ``Delete get_python_source from Kubernetes decorator after bumping min airflow version to 2.6.0 (#36426)`` +`af9328e6ff `_ 2023-12-26 ``Remove duplicated methods in K8S pod operator module and import them from helper function (#36427)`` +`3f60482974 `_ 2023-12-24 ``Don't get pod status in KubernetesPodOperator if skip_on_exit_code is not set (#36355)`` +`63544e184d `_ 2023-12-24 ``Allow changing of 'config_file' in 'KubernetesResourceBaseOperator' (#36397)`` +================================================================================================= =========== ========================================================================================================== + +7.12.0 +...... + +Latest change: 2023-12-23 + +================================================================================================= =========== ================================================================================== +Commit Committed Subject +================================================================================================= =========== ================================================================================== +`b15d5578da `_ 2023-12-23 ``Re-apply updated version numbers to 2nd wave of providers in December (#36380)`` +`f5883d6e7b `_ 2023-12-23 ``Prepare 2nd wave of providers in December (#36373)`` +`33ee0b98b2 `_ 2023-12-22 ``Add _request_timeout to KPO log fetch calls (#36297)`` +`381922f7c0 `_ 2023-12-21 ``Make pod_name length equal to HOST_NAME_MAX (#36332)`` +`49108e15eb `_ 2023-12-20 ``Kubernetes executor running slots leak fix (#36240)`` +`5ab43d5541 `_ 2023-12-19 ``Move KubernetesPodTrigger hook to a cached property (#36290)`` +`f81dfd731f `_ 2023-12-17 ``Add 'pod_template_dict' field to 'KubernetesPodOperator' (#33174)`` +`a398d9d4fa `_ 2023-12-16 ``KubernetesPodTrigger: add exception stack trace in TriggerEvent (#35716)`` +`cd476acd8f `_ 2023-12-11 ``Follow BaseHook connection fields method signature in child classes (#36086)`` +`b9c574c61a `_ 2023-12-10 ``list pods performance optimization (#36092)`` +================================================================================================= =========== ================================================================================== + +7.11.0 +...... + +Latest change: 2023-12-08 + +================================================================================================= =========== ================================================================================================= +Commit Committed Subject +================================================================================================= =========== ================================================================================================= +`999b70178a `_ 2023-12-08 ``Prepare docs 1st wave of Providers December 2023 (#36112)`` +`d0918d77ee `_ 2023-12-07 ``Bump minimum Airflow version in providers to Airflow 2.6.0 (#36017)`` +`1264316fe7 `_ 2023-12-05 ``Drive-by improvements to convert_env_vars (#36062)`` +`de71a62848 `_ 2023-12-05 ``fix: KPO typing env_vars (#36048)`` +`f5259376b8 `_ 2023-11-28 ``Use fail instead of change_state(failed) in K8S executor (#35900)`` +`623f989329 `_ 2023-11-27 ``Stop converting state to TaskInstanceState when it's None (#35891)`` +`e57232ff8f `_ 2023-11-25 ``Feature pass dictionary configuration in application_file in SparkKubernetesOperator (#35848)`` +================================================================================================= =========== ================================================================================================= + +7.10.0 +...... + +Latest change: 2023-11-24 + +================================================================================================= =========== ============================================================================== +Commit Committed Subject +================================================================================================= =========== ============================================================================== +`0b23d5601c `_ 2023-11-24 ``Prepare docs 2nd wave of Providers November 2023 (#35836)`` +`0e157b38a3 `_ 2023-11-23 ``Fix K8S executor override config using pod_override_object (#35185)`` +`ca97feed18 `_ 2023-11-23 ``Revert Remove PodLoggingStatus object #35422 (#35822)`` +`8dc1b23116 `_ 2023-11-22 ``feat: K8S resource operator - CRD (#35600)`` +`99534e47f3 `_ 2023-11-19 ``Use reproducible builds for provider packages (#35693)`` +`99df205f42 `_ 2023-11-16 ``Fix and reapply templates for provider documentation (#35686)`` +`6f51e502df `_ 2023-11-15 ``Add annotations field into in KubernetesPodOperator (#35641)`` +`486ccba4cf `_ 2023-11-13 ``Remove inconsequential code bits in KPO logging (#35416)`` +`31450bbe3c `_ 2023-11-13 ``Remove non existing params from 'KubernetesResourceBaseOperator' docstring`` +`cd296d2068 `_ 2023-11-12 ``KubernetesExecutor observability Improvements (#35579)`` +`4b1e494f47 `_ 2023-11-10 ``Add bandit to pre-commit to detect common security issues (#34247)`` +================================================================================================= =========== ============================================================================== + +7.9.0 +..... + +Latest change: 2023-11-08 + +================================================================================================= =========== =============================================================================== +Commit Committed Subject +================================================================================================= =========== =============================================================================== +`1b059c57d6 `_ 2023-11-08 ``Prepare docs 1st wave of Providers November 2023 (#35537)`` +`d6c79ce340 `_ 2023-11-07 ``Remove tenancity on KPO logs inner func consume_logs (#35504)`` +`68b3b7b468 `_ 2023-11-07 ``Simplify KPO multi container log reconciliation logic (#35450)`` +`be2c3b9d9e `_ 2023-11-05 ``Remove PodLoggingStatus object (#35422)`` +`c67a2b0413 `_ 2023-11-05 ``Use constant for empty xcom result sentinel (#35451)`` +`a61da3cc87 `_ 2023-11-04 ``Add verificationy that provider docs are as expected (#35424)`` +`2023a76037 `_ 2023-11-03 ``Remove before_log in KPO retry and add traceback when interrupted (#35423)`` +`2b0bfea837 `_ 2023-11-01 ``Add startup_check_interval_seconds to PodManager's await_pod_start (#34231)`` +`3724a029da `_ 2023-11-01 ``Improve clear_not_launched_queued_tasks call duration (#34985)`` +`63cc915cd3 `_ 2023-10-31 ``Switch from Black to Ruff formatter (#35287)`` +================================================================================================= =========== =============================================================================== + +7.8.0 +..... + +Latest change: 2023-10-28 + +================================================================================================= =========== ================================================================================= +Commit Committed Subject +================================================================================================= =========== ================================================================================= +`d1c58d86de `_ 2023-10-28 ``Prepare docs 3rd wave of Providers October 2023 - FIX (#35233)`` +`3592ff4046 `_ 2023-10-28 ``Prepare docs 3rd wave of Providers October 2023 (#35187)`` +`85f0ef35b8 `_ 2023-10-27 ``Added to the rendering of KubernetesOperator V1VolumeMount, sub_path (#35129)`` +`d4002261b5 `_ 2023-10-26 ``Replace blocking IO with async IO in AsyncKubernetesHook (#35162)`` +`4767f48a3b `_ 2023-10-25 ``feat: add hostAliases to pod spec in KubernetesPodOperator (#35063)`` +`4c8c85ccc2 `_ 2023-10-23 ``Consolidate the warning stacklevel in KubernetesPodTrigger (#35079)`` +`dd7ba3cae1 `_ 2023-10-19 ``Pre-upgrade 'ruff==0.0.292' changes in providers (#35053)`` +`b75f9e8806 `_ 2023-10-18 ``Upgrade pre-commits (#35033)`` +`f23170c9dd `_ 2023-10-16 ``D401 Support - A thru Common (Inclusive) (#34934)`` +================================================================================================= =========== ================================================================================= + +7.7.0 +..... + +Latest change: 2023-10-13 + +================================================================================================= =========== ====================================================================== +Commit Committed Subject +================================================================================================= =========== ====================================================================== +`e9987d5059 `_ 2023-10-13 ``Prepare docs 1st wave of Providers in October 2023 (#34916)`` +`0c8e30e43b `_ 2023-10-05 ``Bump min airflow version of providers (#34728)`` +`4234d8db7e `_ 2023-10-04 ``Fix parsing KubernetesPodOperator multiline logs (#34412)`` +`cbb04e5133 `_ 2023-10-01 ``Remove duplicated logs by reusing PodLogsConsumer (#34127)`` +`bd512007e5 `_ 2023-09-28 ``Fix KubernetesPodTrigger startup timeout (#34579)`` +`7ebf4220c9 `_ 2023-09-28 ``Refactor usage of str() in providers (#34320)`` +`fb92ff8486 `_ 2023-09-27 ``Fix Pod not being removed after istio-sidecar is removed (#34500)`` +`a169cf2c25 `_ 2023-09-26 ``Update CHANGELOG.rst (#34625)`` +`08729eddbd `_ 2023-09-22 ``warn level for deprecated set to stacklevel 2 (#34530)`` +`659d94f0ae `_ 2023-09-21 ``Use 'airflow.exceptions.AirflowException' in providers (#34511)`` +`8ecd576de1 `_ 2023-09-14 ``Refactor shorter defaults in providers (#34347)`` +================================================================================================= =========== ====================================================================== + +7.6.0 +..... + +Latest change: 2023-09-14 + +================================================================================================= =========== ========================================================================= +Commit Committed Subject +================================================================================================= =========== ========================================================================= +`7574e16e75 `_ 2023-09-14 ``Prepare docs for Sep 2023 2nd wave of Providers (#34360)`` +`de92a81f00 `_ 2023-09-13 ``Move definition of Pod*Exceptions to pod_generator (#34346)`` +`b435b8edef `_ 2023-09-09 ``Push to xcom before 'KubernetesPodOperator' deferral (#34209)`` +`b5057e0e1f `_ 2023-09-09 ``Add 'progress_callback' parameter to 'KubernetesPodOperator' (#34153)`` +`c5016f754d `_ 2023-09-08 ``Refactor: Consolidate import textwrap in providers (#34220)`` +================================================================================================= =========== ========================================================================= + +7.5.1 +..... + +Latest change: 2023-09-08 + +================================================================================================= =========== ================================================================================================= +Commit Committed Subject +================================================================================================= =========== ================================================================================================= +`21990ed894 `_ 2023-09-08 ``Prepare docs for 09 2023 - 1st wave of Providers (#34201)`` +`6e1de4f9b9 `_ 2023-09-07 ``fix(providers/spark-kubernetes): respect soft_fail argument when exception is raised (#34167)`` +`1005501365 `_ 2023-09-06 ``Used cached property for hook in SparkKubernetesOperator (#34130)`` +`7731255975 `_ 2023-09-06 ``Refactor: Consolidate import datetime (#34110)`` +`5e6e107f73 `_ 2023-09-05 ``Use 'cached_property' for hook in SparkKubernetesSensor (#34106)`` +`fa5e54c4c5 `_ 2023-09-03 ``Combine similar if logics in providers (#33987)`` +`47bd5dd0e1 `_ 2023-09-03 ``Remove useless string join from providers (#33968)`` +`875387afa5 `_ 2023-09-01 ``Refactor unneeded jumps in providers (#33833)`` +`ff7dcf4e82 `_ 2023-09-01 ``replace loop by any when looking for a positive value in providers (#33984)`` +`1b122c1503 `_ 2023-09-01 ``Move the try outside the loop when this is possible in kubernetes provider (#33977)`` +`55976af32e `_ 2023-08-31 ``Replace sequence concatination by unpacking in Airflow providers (#33933)`` +`f66df7f6bc `_ 2023-08-31 ``Replace dict.items by values when key is not used in providers (#33939)`` +================================================================================================= =========== ================================================================================================= + +7.5.0 +..... + +Latest change: 2023-08-29 + +================================================================================================= =========== ================================================================================================================ +Commit Committed Subject +================================================================================================= =========== ================================================================================================================ +`23174ef1bb `_ 2023-08-29 ``Prepare docs for Aug 2023 3rd wave of Providers (RC2) (#33868)`` +`cede385e93 `_ 2023-08-28 ``Always use 'Literal' from 'typing_extensions' (#33794)`` +`452a978337 `_ 2023-08-27 ``Improve modules import in cncf.kubernetes probvider by move some of them into a type-checking block (#33781)`` +`42bc8fcb6b `_ 2023-08-26 ``Update pod.py (#33779)`` +`b11525702c `_ 2023-08-26 ``Use literal dict instead of calling dict() in providers (#33761)`` +`c077d19060 `_ 2023-08-26 ``Prepare docs for Aug 2023 3rd wave of Providers (#33730)`` +`c477031039 `_ 2023-08-24 ``Inspect container state rather than last_state when deciding whether to skip (#33702)`` +`85acbb4ae9 `_ 2023-08-24 ``Refactor: Remove useless str() calls (#33629)`` +`6130993d78 `_ 2023-08-24 ``Fix KubernetesPodOperator duplicating logs when interrupted (#33500)`` +`2dbb963324 `_ 2023-08-24 ``Refactor: Improve detection of duplicates and list sorting (#33675)`` +`75ce4d1923 `_ 2023-08-23 ``Add istio test, use curl /quitquitquit to exit sidecar, and some othe… (#33306)`` +`4bdf908041 `_ 2023-08-23 ``Fix 2.7.0 db migration job errors (#33652)`` +`0ca5f700ab `_ 2023-08-23 ``Exclude deprecated "operators.kubernetes_pod" module from provider.yaml (#33641)`` +`a54c2424df `_ 2023-08-23 ``Fix typos (double words and it's/its) (#33623)`` +`7141c42cc3 `_ 2023-08-22 ``Make cluster_context templated (#33604)`` +`4c4981d1ad `_ 2023-08-21 ``Refactor Sqlalchemy queries to 2.0 style (Part 7) (#32883)`` +`95a930bc0a `_ 2023-08-21 ``Consolidate import and usage of itertools (#33479)`` +`1cdd82391e `_ 2023-08-21 ``Simplify conditions on len() in other providers (#33569)`` +`e991f60a79 `_ 2023-08-18 ``Add 'active_deadline_seconds' parameter to 'KubernetesPodOperator' (#33379)`` +`bfe08a79db `_ 2023-08-16 ``Import utc from datetime and normalize its import (#33450)`` +`46ffc25995 `_ 2023-08-14 ``Adding typing for KPO SCC objects (#33381)`` +`38aada7b8b `_ 2023-08-14 ``Introducing class constant to make worker pod log lines configurable (#33378)`` +`7e79997594 `_ 2023-08-11 ``D205 Support - Providers - Final Pass (#33303)`` +================================================================================================= =========== ================================================================================================================ + +7.4.2 +..... + +Latest change: 2023-08-11 + +================================================================================================= =========== ============================================================================================================== +Commit Committed Subject +================================================================================================= =========== ============================================================================================================== +`b5a4d36383 `_ 2023-08-11 ``Prepare docs for Aug 2023 2nd wave of Providers (#33291)`` +`1f6257110d `_ 2023-08-09 ``Make the 'OnFinishAction' enum inherit from str to support passing it to 'KubernetesPodOperatpor' (#33228)`` +`0b528e2b2e `_ 2023-08-09 ``Add missing re2 dependency to cncf.kubernetes and celery providers (#33237)`` +`056f1670fe `_ 2023-08-08 ``Refactor: Simplify code in providers/cncf (#33230)`` +`9556d6d5f6 `_ 2023-08-08 ``Replace State by TaskInstanceState in Airflow executors (#32627)`` +================================================================================================= =========== ============================================================================================================== + +7.4.1 +..... + +Latest change: 2023-08-05 + +================================================================================================= =========== ======================================================================================================= +Commit Committed Subject +================================================================================================= =========== ======================================================================================================= +`60677b0ba3 `_ 2023-08-05 ``Prepare docs for Aug 2023 1st wave of Providers (#33128)`` +`f4542a30b0 `_ 2023-08-04 ``Fix waiting the base container when reading the logs of other containers (#33127)`` +`4fbbdbc9b1 `_ 2023-08-04 ``Revert "Fix waiting the base container when reading the logs of other containers (#33092)" (#33125)`` +`164526d4c7 `_ 2023-08-04 ``Consider custom pod labels on pod finding process on 'KubernetesPodOperator' (#33057)`` +`d31c77510c `_ 2023-08-04 ``Fix waiting the base container when reading the logs of other containers (#33092)`` +`900ad8c190 `_ 2023-08-04 ``Fix: Configurable Docker image of 'xcom_sidecar' (#32858)`` +`879fd34e97 `_ 2023-08-04 ``aDd documentation generation for CLI commands from executors (#33081)`` +`f83d63ea54 `_ 2023-08-04 ``Fix 'KubernetesPodOperator' sub classes default container_logs (#33090)`` +================================================================================================= =========== ======================================================================================================= + +7.4.0 +..... + +Latest change: 2023-07-29 + +================================================================================================= =========== ================================================================================== +Commit Committed Subject +================================================================================================= =========== ================================================================================== +`d06b7af69a `_ 2023-07-29 ``Prepare docs for July 2023 3rd wave of Providers (#32875)`` +`bcc7856b80 `_ 2023-07-29 ``Add 'termination_message_policy' parameter to 'KubernetesPodOperator' (#32885)`` +`f31af91dbd `_ 2023-07-29 ``Raise original import error in CLI vending of executors (#32931)`` +`fcbbf47864 `_ 2023-07-29 ``[AIP-51] Executors vending CLI commands (#29055)`` +`e93460383f `_ 2023-07-26 ``Move all k8S classes to cncf.kubernetes provider (#32767)`` +`fcc6f284c7 `_ 2023-07-22 ``Update the watcher resource version in SparkK8SOp when it's too old (#32768)`` +`e01323635a `_ 2023-07-13 ``Add deprecation info to the providers modules and classes docstring (#32536)`` +================================================================================================= =========== ================================================================================== + +7.3.0 +..... + +Latest change: 2023-07-12 + +================================================================================================= =========== ========================================================================================== +Commit Committed Subject +================================================================================================= =========== ========================================================================================== +`e7f59a913e `_ 2023-07-12 ``Prepare docs for July 2023 2nd wave of Providers (#32566)`` +`b3ce116192 `_ 2023-07-12 ``Fix async KPO by waiting pod termination in 'execute_complete' before cleanup (#32467)`` +`c99c03135c `_ 2023-07-08 ``D205 Support - Providers: Stragglers and new additions (#32447)`` +`9a0f41ba53 `_ 2023-07-06 ``Logging from all containers in KubernetesOperatorPod (#31663)`` +================================================================================================= =========== ========================================================================================== + +7.2.0 +..... + +Latest change: 2023-07-06 + +================================================================================================= =========== ========================================================================= +Commit Committed Subject +================================================================================================= =========== ========================================================================= +`225e3041d2 `_ 2023-07-06 ``Prepare docs for July 2023 wave of Providers (RC2) (#32381)`` +`3878fe6fab `_ 2023-07-05 ``Remove spurious headers for provider changelogs (#32373)`` +`cb4927a018 `_ 2023-07-05 ``Prepare docs for July 2023 wave of Providers (#32298)`` +`f8593503cb `_ 2023-07-05 ``Add default_deferrable config (#31712)`` +`df4c8837d0 `_ 2023-07-01 ``Fix KubernetesPodOperator validate xcom json and add retries (#32113)`` +`dd937e51fe `_ 2023-06-30 ``Add 'on_finish_action' to 'KubernetesPodOperator' (#30718)`` +`8f5de83ee6 `_ 2023-06-29 ``Fix 'KubernetesPodTrigger' waiting strategy (#31348)`` +`8c37b74a20 `_ 2023-06-28 ``D205 Support - Providers: Apache to Common (inclusive) (#32226)`` +`6693bdd72d `_ 2023-06-27 ``fix spark-kubernetes-operator compatibality (#31798)`` +`09d4718d3a `_ 2023-06-27 ``Improve provider documentation and README structure (#32125)`` +================================================================================================= =========== ========================================================================= + +7.1.0 +..... + +Latest change: 2023-06-20 + +================================================================================================= =========== ============================================================================================================= +Commit Committed Subject +================================================================================================= =========== ============================================================================================================= +`79bcc2e668 `_ 2023-06-20 ``Prepare RC1 docs for June 2023 wave of Providers (#32001)`` +`8b146152d6 `_ 2023-06-20 ``Add note about dropping Python 3.7 for providers (#32015)`` +`66299338eb `_ 2023-06-18 ``add a return when the event is yielded in a loop to stop the execution (#31985)`` +`07ea574fed `_ 2023-06-07 ``Add D400 pydocstyle check (#31742)`` +`d8086a3db5 `_ 2023-06-05 ``Add possibility to disable logging the pod template in a case when task fails (#31595)`` +`def4b53765 `_ 2023-06-05 ``Fix Fargate logging for AWS system tests (#31622)`` +`86b5ba2802 `_ 2023-06-04 ``Remove return statement after yield from triggers class (#31703)`` +`0fa8c44527 `_ 2023-06-04 ``KubernetesResourceOperator - KubernetesDeleteResourceOperator & KubernetesCreateResourceOperator (#29930)`` +`dc5bf3fd02 `_ 2023-06-02 ``Add discoverability for triggers in provider.yaml (#31576)`` +`a59076eaee `_ 2023-06-02 ``Add D400 pydocstyle check - Providers (#31427)`` +`9fa75aaf7a `_ 2023-05-29 ``Remove Python 3.7 support (#30963)`` +================================================================================================= =========== ============================================================================================================= + +7.0.0 +..... + +Latest change: 2023-05-19 + +================================================================================================= =========== ================================================================================================ +Commit Committed Subject +================================================================================================= =========== ================================================================================================ +`45548b9451 `_ 2023-05-19 ``Prepare RC2 docs for May 2023 wave of Providers (#31416)`` +`a1f5a5425e `_ 2023-05-19 ``Remove deprecated features from KubernetesHook (#31402)`` +`54f1fb0574 `_ 2023-05-19 ``Docstring improvements (#31375)`` +`abea189022 `_ 2023-05-18 ``Use '__version__' in providers not 'version' (#31393)`` +`f5aed58d9f `_ 2023-05-18 ``Fixing circular import error in providers caused by airflow version check (#31379)`` +`d9ff55cf6d `_ 2023-05-16 ``Prepare docs for May 2023 wave of Providers (#31252)`` +`caeca2d143 `_ 2023-05-15 ``Add protocol to define methods relied upon by KubernetesPodOperator (#31298)`` +`774a5a9038 `_ 2023-05-11 ``Empty xcom result file log message more specific (#31228)`` +`e7cb9ca2c1 `_ 2023-05-11 ``Fix pod describing on system test failure (#31191)`` +`8eab2e54ee `_ 2023-05-10 ``K8s hook should still work with missing default conn (#31187)`` +`c3c90eaa94 `_ 2023-05-10 ``Add options to KubernetesPodOperator (#30992)`` +`dcf3d39a15 `_ 2023-05-08 ``Fix kubernetes task decorator pickle error (#31110)`` +`0a30706aa7 `_ 2023-05-03 ``Use 'AirflowProviderDeprecationWarning' in providers (#30975)`` +`eef5bc7f16 `_ 2023-05-03 ``Add full automation for min Airflow version for providers (#30994)`` +`a7eb32a5b2 `_ 2023-04-30 ``Bump minimum Airflow version in providers (#30917)`` +`9409446097 `_ 2023-04-24 ``Add cli cmd to list the provider trigger info (#30822)`` +`b5296b7436 `_ 2023-04-22 ``add missing read for K8S config file from conn in deferred 'KubernetesPodOperator' (#29498)`` +`c585ad51c5 `_ 2023-04-22 ``Upgrade ruff to 0.0.262 (#30809)`` +================================================================================================= =========== ================================================================================================ + +6.1.0 +..... + +Latest change: 2023-04-21 + +================================================================================================= =========== =========================================================================================================== +Commit Committed Subject +================================================================================================= =========== =========================================================================================================== +`e46ce78b66 `_ 2023-04-21 ``Prepare docs for adhoc release of providers (#30787)`` +`ebe2f2f626 `_ 2023-04-21 ``Remove skip_exit_code from KubernetesPodOperator (#30788)`` +`afdc95435b `_ 2023-04-21 ``Add multiple exit code handling in skip logic for 'DockerOperator' and 'KubernetesPodOperator' (#30769)`` +`99a3bf2318 `_ 2023-04-19 ``Deprecate 'skip_exit_code' in 'DockerOperator' and 'KubernetesPodOperator' (#30733)`` +`f511653e5a `_ 2023-04-15 ``Skip KubernetesPodOperator task when it returns a provided exit code (#29000)`` +================================================================================================= =========== =========================================================================================================== + +6.0.0 +..... + +Latest change: 2023-04-09 + +================================================================================================= =========== ================================================================ +Commit Committed Subject +================================================================================================= =========== ================================================================ +`874ea9588e `_ 2023-04-09 ``Prepare docs for ad hoc release of Providers (#30545)`` +`85b9135722 `_ 2023-04-08 ``Use default connection id for KubernetesPodOperator (#28848)`` +`dc4dd9178c `_ 2023-04-05 ``Allow to set limits for XCOM container (#28125)`` +`d23a3bbed8 `_ 2023-04-04 ``Add mechanism to suspend providers (#30422)`` +================================================================================================= =========== ================================================================ + +5.3.0 +..... + +Latest change: 2023-04-02 + +================================================================================================= =========== ========================================================================== +Commit Committed Subject +================================================================================================= =========== ========================================================================== +`55dbf1ff1f `_ 2023-04-02 ``Prepare docs for April 2023 wave of Providers (#30378)`` +`df49ad179b `_ 2023-03-24 ``Ensure setup/teardown work on a previously decorated function (#30216)`` +`b8ab594130 `_ 2023-03-15 ``Remove "boilerplate" from all taskflow decorators (#30118)`` +`9a4f674852 `_ 2023-03-14 ``enhance spark_k8s_operator (#29977)`` +`c3867781e0 `_ 2023-03-08 ``adding trigger info to provider yaml (#29950)`` +`1e81a98cc6 `_ 2023-03-07 ``Fix KubernetesPodOperator xcom push when 'get_logs=False' (#29052)`` +`971039454a `_ 2023-03-04 ``Align cncf provider file names with AIP-21 (#29905)`` +`6d2face107 `_ 2023-03-04 ``Fixed hanged KubernetesPodOperator (#28336)`` +================================================================================================= =========== ========================================================================== + +5.2.2 +..... + +Latest change: 2023-03-03 + +================================================================================================= =========== =================================================================================================================== +Commit Committed Subject +================================================================================================= =========== =================================================================================================================== +`fcd3c0149f `_ 2023-03-03 ``Prepare docs for 03/2023 wave of Providers (#29878)`` +`1e536eb43d `_ 2023-02-28 ``'KubernetesPodOperator._render_nested_template_fields' improved by changing the conditionals for a map (#29760)`` +`dba390e323 `_ 2023-02-22 ``Fix and augment 'check-for-inclusive-language' CI check (#29549)`` +================================================================================================= =========== =================================================================================================================== + +5.2.1 +..... + +Latest change: 2023-02-18 + +================================================================================================= =========== ================================================================== +Commit Committed Subject +================================================================================================= =========== ================================================================== +`470fdaea27 `_ 2023-02-18 ``Prepare docs for 02 2023 midmonth wave of Providers (#29589)`` +`9a5c3e0ac0 `_ 2023-02-18 ``Fix @task.kubernetes to receive input and send output (#28942)`` +================================================================================================= =========== ================================================================== + +5.2.0 +..... + +Latest change: 2023-02-08 + +================================================================================================= =========== ================================================================================== +Commit Committed Subject +================================================================================================= =========== ================================================================================== +`ce6ae2457e `_ 2023-02-08 ``Prepare docs for Feb 2023 wave of Providers (#29379)`` +`d26dc22391 `_ 2023-02-01 ``Patch only single label when marking KPO checked (#29279)`` +`246d778e6b `_ 2023-01-30 ``Add deferrable mode to ''KubernetesPodOperator'' (#29017)`` +`70b84b51a5 `_ 2023-01-23 ``Allow setting the name for the base container within K8s Pod Operator (#28808)`` +================================================================================================= =========== ================================================================================== + +5.1.1 +..... + +Latest change: 2023-01-14 + +================================================================================================= =========== ================================================================== +Commit Committed Subject +================================================================================================= =========== ================================================================== +`911b708ffd `_ 2023-01-14 ``Prepare docs for Jan 2023 mid-month wave of Providers (#28929)`` +`ce858a5d71 `_ 2023-01-12 ``Switch to ruff for faster static checks (#28893)`` +`ce677862be `_ 2023-01-07 ``Fix Incorrect 'await_container_completion' (#28771)`` +================================================================================================= =========== ================================================================== + +5.1.0 +..... + +Latest change: 2023-01-02 + +================================================================================================= =========== ======================================================================== +Commit Committed Subject +================================================================================================= =========== ======================================================================== +`5246c009c5 `_ 2023-01-02 ``Prepare docs for Jan 2023 wave of Providers (#28651)`` +`c22fc000b6 `_ 2022-12-30 ``Use labels instead of pod name for pod log read in k8s exec (#28546)`` +`681835a67c `_ 2022-12-21 ``Add Flink on K8s Operator (#28512)`` +`38e40c6dc4 `_ 2022-12-21 ``Remove outdated compat imports/code from providers (#28507)`` +`401fc57e8b `_ 2022-12-16 ``Restructure Docs (#27235)`` +`bdc3d2e647 `_ 2022-12-08 ``Keep pod name for k8s executor under 63 characters (#28237)`` +`d93240696b `_ 2022-12-05 ``Allow longer pod names for k8s executor / KPO (#27736)`` +`33c445d92f `_ 2022-12-03 ``Add volume-related nested template fields for KPO (#27719)`` +`ebd7b67dcb `_ 2022-12-02 ``Patch "checked" when pod not successful (#27845)`` +`25bdbc8e67 `_ 2022-11-26 ``Updated docs for RC3 wave of providers (#27937)`` +`2e20e9f7eb `_ 2022-11-24 ``Prepare for follow-up relase for November providers (#27774)`` +================================================================================================= =========== ======================================================================== + +5.0.0 +..... + +Latest change: 2022-11-15 + +================================================================================================= =========== ============================================================================================ +Commit Committed Subject +================================================================================================= =========== ============================================================================================ +`12c3c39d1a `_ 2022-11-15 ``pRepare docs for November 2022 wave of Providers (#27613)`` +`52593b061c `_ 2022-11-11 ``Enable template rendering for env_vars field for the @task.kubernetes decorator (#27433)`` +`47a2b9ee7f `_ 2022-11-09 ``Add container_resources as KubernetesPodOperator templatable (#27457)`` +`aefadb8c5b `_ 2022-11-08 ``Allow xcom sidecar container image to be configurable in KPO (#26766)`` +`2d2f0daad6 `_ 2022-11-08 ``Fix KubernetesHook fail on an attribute absence (#25787)`` +`eee3df4570 `_ 2022-11-07 ``Improve task_id to pod name conversion (#27524)`` +`8c15b0a6d1 `_ 2022-11-07 ``Use log.exception where more economical than log.error (#27517)`` +`20ecefa416 `_ 2022-11-05 ``KPO should use hook's get namespace method to get namespace (#27516)`` +`701239abc3 `_ 2022-11-05 ``Remove deprecated backcompat objects for KPO (#27518)`` +`9337aa92c0 `_ 2022-11-05 ``Remove support for node_selectors param in KPO (#27515)`` +`3aadc44a13 `_ 2022-11-03 ``Remove unused backcompat method in k8s hook (#27490)`` +`0c26ec07be `_ 2022-10-28 ``Drop support for providing ''resource'' as dict in ''KubernetesPodOperator'' (#27197)`` +`4797a0322e `_ 2022-10-28 ``Fix log message for kubernetes hooks (#26999)`` +`9ab1a6a3e7 `_ 2022-10-27 ``Update old style typing (#26872)`` +`734995ff26 `_ 2022-10-26 ``Add deprecation warning re unset namespace in k8s hook (#27202)`` +`78b8ea2f22 `_ 2022-10-24 ``Move min airflow version to 2.3.0 for all providers (#27196)`` +`2a34dc9e84 `_ 2022-10-23 ``Enable string normalization in python formatting - providers (#27205)`` +`14a45872e2 `_ 2022-10-22 ``Remove extra__kubernetes__ prefix from k8s hook extras (#27021)`` +`3ecb8dd025 `_ 2022-10-22 ``Make namespace optional for KPO (#27116)`` +`c9e57687b0 `_ 2022-10-21 ``Make pod name optional in KubernetesPodOperator (#27120)`` +`2752f2add1 `_ 2022-10-12 ``Deprecate use of core get_kube_client in PodManager (#26848)`` +`5c97e5be48 `_ 2022-10-10 ``add container_name option for SparkKubernetesSensor (#26560)`` +`53d68049d9 `_ 2022-10-04 ``Don't consider airflow core conf for KPO (#26849)`` +`f8db64c35c `_ 2022-09-28 ``Update docs for September Provider's release (#26731)`` +================================================================================================= =========== ============================================================================================ + +4.4.0 +..... + +Latest change: 2022-09-22 + +================================================================================================= =========== ==================================================================================== +Commit Committed Subject +================================================================================================= =========== ==================================================================================== +`1a07cbe423 `_ 2022-09-22 ``Prepare to release cncf.kubernetes provider (#26588)`` +`e60a459d56 `_ 2022-09-14 ``Avoid calculating all elements when one item is needed (#26377)`` +`06acf40a43 `_ 2022-09-13 ``Apply PEP-563 (Postponed Evaluation of Annotations) to non-core airflow (#26289)`` +`4b26c8c541 `_ 2022-09-09 ``feat(KubernetesPodOperator): Add support of container_security_context (#25530)`` +`0eb0b543a9 `_ 2022-08-23 ``Add @task.kubernetes taskflow decorator (#25663)`` +`db5543ef60 `_ 2022-08-22 ``pretty print KubernetesPodOperator rendered template env_vars (#25850)`` +`ccdd73ec50 `_ 2022-08-22 ``Wait for xcom sidecar container to start before sidecar exec (#25055)`` +================================================================================================= =========== ==================================================================================== + +4.3.0 +..... + +Latest change: 2022-08-10 + +================================================================================================= =========== ================================================================= +Commit Committed Subject +================================================================================================= =========== ================================================================= +`e5ac6c7cfb `_ 2022-08-10 ``Prepare docs for new providers release (August 2022) (#25618)`` +`c8af0592c0 `_ 2022-07-26 ``Improve taskflow type hints with ParamSpec (#25173)`` +`f05a06537b `_ 2022-07-16 ``Fix xcom_sidecar stuck problem (#24993)`` +================================================================================================= =========== ================================================================= + +4.2.0 +..... + +Latest change: 2022-07-13 + +================================================================================================= =========== ============================================================================= +Commit Committed Subject +================================================================================================= =========== ============================================================================= +`d2459a241b `_ 2022-07-13 ``Add documentation for July 2022 Provider's release (#25030)`` +`ef79a0d1c4 `_ 2022-07-11 ``Only assert stuff for mypy when type checking (#24937)`` +`e2fd41f7b1 `_ 2022-07-04 ``Remove 'xcom_push' flag from providers (#24823)`` +`9d307102b4 `_ 2022-06-29 ``More typing and minor refactor for kubernetes (#24719)`` +`0de31bd73a `_ 2022-06-29 ``Move provider dependencies to inside provider folders (#24672)`` +`45b11d4ed1 `_ 2022-06-29 ``Use our yaml util in all providers (#24720)`` +`510a6bab45 `_ 2022-06-28 ``Remove 'hook-class-names' from provider.yaml (#24702)`` +`5326da4b83 `_ 2022-06-28 ``Add 'airflow_kpo_in_cluster' label to KPO pods (#24658)`` +`45f4290712 `_ 2022-06-28 ``Rename 'resources' arg in Kub op to k8s_resources (#24673)`` +`9c59831ee7 `_ 2022-06-21 ``Update providers to use functools compat for ''cached_property'' (#24582)`` +`78ac48872b `_ 2022-06-21 ``Use found pod for deletion in KubernetesPodOperator (#22092)`` +`dba3e4ec51 `_ 2022-06-15 ``Revert "Fix await_container_completion condition (#23883)" (#24474)`` +================================================================================================= =========== ============================================================================= + +4.1.0 +..... + +Latest change: 2022-06-09 + +================================================================================================= =========== ================================================================================== +Commit Committed Subject +================================================================================================= =========== ================================================================================== +`dcdcf3a2b8 `_ 2022-06-09 ``Update release notes for RC2 release of Providers for May 2022 (#24307)`` +`717a7588bc `_ 2022-06-07 ``Update package description to remove double min-airflow specification (#24292)`` +`b1ad017cee `_ 2022-06-07 ``pydocstyle D202 added (#24221)`` +`aeabe994b3 `_ 2022-06-07 ``Prepare docs for May 2022 provider's release (#24231)`` +`98b4e48fbc `_ 2022-06-06 ``Add param docs to KubernetesHook and KubernetesPodOperator (#23955) (#24054)`` +`42abbf0d61 `_ 2022-06-06 ``Fix await_container_completion condition (#23883)`` +`027b707d21 `_ 2022-06-05 ``Add explanatory note for contributors about updating Changelog (#24229)`` +`7ad4e67c1a `_ 2022-06-03 ``Migrate Cncf.Kubernetes example DAGs to new design #22441 (#24132)`` +`60eb9e106f `_ 2022-05-31 ``Use KubernetesHook to create api client in KubernetesPodOperator (#20578)`` +`e240132934 `_ 2022-05-27 ``[FEATURE] KPO use K8S hook (#22086)`` +`6bbe015905 `_ 2022-05-26 ``Use "remote" pod when patching KPO pod as "checked" (#23676)`` +`ec6761a5c0 `_ 2022-05-23 ``Clean up f-strings in logging calls (#23597)`` +`064c41afda `_ 2022-05-20 ``Don't use the root logger in KPO _suppress function (#23835)`` +================================================================================================= =========== ================================================================================== + +4.0.2 +..... + +Latest change: 2022-05-12 + +================================================================================================= =========== =========================================================================================================== +Commit Committed Subject +================================================================================================= =========== =========================================================================================================== +`75c60923e0 `_ 2022-05-12 ``Prepare provider documentation 2022.05.11 (#23631)`` +`2eeb120bf4 `_ 2022-05-12 ``Revert "Fix k8s pod.execute randomly stuck indefinitely by logs consumption (#23497) (#23618)" (#23656)`` +`ee342b85b9 `_ 2022-05-11 ``Fix k8s pod.execute randomly stuck indefinitely by logs consumption (#23497) (#23618)`` +`863b257642 `_ 2022-05-10 ``Fix: Exception when parsing log #20966 (#23301)`` +`faae9faae3 `_ 2022-05-10 ``Fixed Kubernetes Operator large xcom content Defect (#23490)`` +`dbdcd0fd1d `_ 2022-04-30 ``Clarify 'reattach_on_restart' behavior (#23377)`` +`a914ec22c1 `_ 2022-04-30 ``Add YANKED to yanked releases of the cncf.kubernetes (#23378)`` +================================================================================================= =========== =========================================================================================================== + +4.0.1 +..... + +Latest change: 2022-04-30 + +================================================================================================= =========== ==================================================================================== +Commit Committed Subject +================================================================================================= =========== ==================================================================================== +`11bbe471cd `_ 2022-04-30 ``Prepare documentation for cncf.kubernetes 4.0.1 release (#23374)`` +`8e3abe4180 `_ 2022-04-29 ``Fix ''KubernetesPodOperator'' with 'KubernetesExecutor'' on 2.3.0 (#23371)`` +`8b6b0848a3 `_ 2022-04-23 ``Use new Breese for building, pulling and verifying the images. (#23104)`` +`c7399c7190 `_ 2022-04-21 ``KubernetesHook should try incluster first when not otherwise configured (#23126)`` +`70eede5dd6 `_ 2022-04-20 ``Fix KPO to have hyphen instead of period (#22982)`` +`c3d883a971 `_ 2022-04-19 ``KubernetesPodOperator should patch "already checked" always (#22734)`` +`d81703c577 `_ 2022-04-14 ``Add k8s container's error message in airflow exception (#22871)`` +`3c5bc73579 `_ 2022-04-12 ``Delete old Spark Application in SparkKubernetesOperator (#21092)`` +`6933022e94 `_ 2022-04-10 ``Fix new MyPy errors in main (#22884)`` +`04082ac091 `_ 2022-04-09 ``Cleanup dup code now that k8s provider requires 2.3.0+ (#22845)`` +================================================================================================= =========== ==================================================================================== + +4.0.0 +..... + +Latest change: 2022-04-07 + +================================================================================================= =========== ============================================================================== +Commit Committed Subject +================================================================================================= =========== ============================================================================== +`56ab82ed7a `_ 2022-04-07 ``Prepare mid-April provider documentation. (#22819)`` +`67e2723b73 `_ 2022-03-29 ``Log traceback only on ''DEBUG'' for KPO logs read interruption (#22595)`` +`6db30f3207 `_ 2022-03-29 ``Update our approach for executor-bound dependencies (#22573)`` +`0d64d66cea `_ 2022-03-28 ``Stop crashing when empty logs are received from kubernetes client (#22566)`` +`0a99be7411 `_ 2022-03-22 ``Optionally not follow logs in KPO pod_manager (#22412)`` +================================================================================================= =========== ============================================================================== + +3.1.2 +..... + +Latest change: 2022-03-22 + +================================================================================================= =========== ============================================================================== +Commit Committed Subject +================================================================================================= =========== ============================================================================== +`d7dbfb7e26 `_ 2022-03-22 ``Add documentation for bugfix release of Providers (#22383)`` +`0f977daa3c `_ 2022-03-22 ``Fix "run_id" k8s and elasticsearch compatibility with Airflow 2.1 (#22385)`` +`7bd165fbe2 `_ 2022-03-16 ``Remove RefreshConfiguration workaround for K8s token refreshing (#20759)`` +================================================================================================= =========== ============================================================================== + +3.1.1 +..... + +Latest change: 2022-03-14 + +================================================================================================= =========== ==================================================================== +Commit Committed Subject +================================================================================================= =========== ==================================================================== +`16adc035b1 `_ 2022-03-14 ``Add documentation for Classifier release for March 2022 (#22226)`` +================================================================================================= =========== ==================================================================== + +3.1.0 +..... + +Latest change: 2022-03-07 + +================================================================================================= =========== ======================================================================== +Commit Committed Subject +================================================================================================= =========== ======================================================================== +`f5b96315fe `_ 2022-03-07 ``Add documentation for Feb Providers release (#22056)`` +`8d8d072289 `_ 2022-03-03 ``Change KubePodOperator labels from exeuction_date to run_id (#21960)`` +`6c37e47cf6 `_ 2022-03-02 ``Add map_index label to mapped KubernetesPodOperator (#21916)`` +`351fa53432 `_ 2022-03-01 ``Fix Kubernetes example with wrong operator casing (#21898)`` +`a159ae828f `_ 2022-02-25 ``Remove types from KPO docstring (#21826)`` +`0a3ff43d41 `_ 2022-02-08 ``Add pre-commit check for docstring param types (#21398)`` +================================================================================================= =========== ======================================================================== + +3.0.2 +..... + +Latest change: 2022-02-08 + +================================================================================================= =========== ========================================================================== +Commit Committed Subject +================================================================================================= =========== ========================================================================== +`d94fa37830 `_ 2022-02-08 ``Fixed changelog for January 2022 (delayed) provider's release (#21439)`` +`6c3a67d4fc `_ 2022-02-05 ``Add documentation for January 2021 providers release (#21257)`` +`4a73d8f3d1 `_ 2022-02-01 ``Add missed deprecations for cncf (#20031)`` +`cb73053211 `_ 2022-01-27 ``Add optional features in providers. (#21074)`` +`602abe8394 `_ 2022-01-20 ``Remove ':type' lines now sphinx-autoapi supports typehints (#20951)`` +`428bd5f228 `_ 2022-01-10 ``Make ''delete_pod'' change more prominent in K8s changelog (#20753)`` +`5569b868a9 `_ 2022-01-09 ``Fix MyPy Errors for providers: Tableau, CNCF, Apache (#20654)`` +================================================================================================= =========== ========================================================================== + +3.0.1 +..... + +Latest change: 2022-01-08 + +================================================================================================= =========== =================================================================== +Commit Committed Subject +================================================================================================= =========== =================================================================== +`da9210e89c `_ 2022-01-08 ``Add documentation for an ad-hoc release of 2 providers (#20765)`` +`7222f68d37 `_ 2022-01-04 ``Update Kubernetes library version (#18797)`` +================================================================================================= =========== =================================================================== + +3.0.0 +..... + +Latest change: 2021-12-31 + +================================================================================================= =========== ================================================================================= +Commit Committed Subject +================================================================================================= =========== ================================================================================= +`f77417eb0d `_ 2021-12-31 ``Fix K8S changelog to be PyPI-compatible (#20614)`` +`97496ba2b4 `_ 2021-12-31 ``Update documentation for provider December 2021 release (#20523)`` +`83f8e178ba `_ 2021-12-31 ``Even more typing in operators (template_fields/ext) (#20608)`` +`746ee587da `_ 2021-12-31 ``Delete pods by default in KubernetesPodOperator (#20575)`` +`d56ff765e1 `_ 2021-12-30 ``Implement dry_run for KubernetesPodOperator (#20573)`` +`e63417553f `_ 2021-12-30 ``Move pod_mutation_hook call from PodManager to KubernetesPodOperator (#20596)`` +`ca6c210b7d `_ 2021-12-30 ``Rename ''PodLauncher'' to ''PodManager'' (#20576)`` +`e07e831946 `_ 2021-12-30 ``Clarify docstring for ''build_pod_request_obj'' in K8s providers (#20574)`` +`d56e7b56bb `_ 2021-12-30 ``Fix template_fields type to have MyPy friendly Sequence type (#20571)`` +`a0821235fb `_ 2021-12-30 ``Use typed Context EVERYWHERE (#20565)`` +`f200bb1977 `_ 2021-12-29 ``Simplify ''KubernetesPodOperator'' (#19572)`` +`4b8a1201ae `_ 2021-12-16 ``Fix Volume/VolumeMount KPO DeprecationWarning (#19726)`` +`2fb5e1d0ec `_ 2021-12-15 ``Fix cached_property MyPy declaration and related MyPy errors (#20226)`` +`f9eab1c185 `_ 2021-12-06 ``Add params config, in_cluster, and cluster_context to KubernetesHook (#19695)`` +================================================================================================= =========== ================================================================================= + +2.2.0 +..... + +Latest change: 2021-11-30 + +================================================================================================= =========== ====================================================================== +Commit Committed Subject +================================================================================================= =========== ====================================================================== +`853576d901 `_ 2021-11-30 ``Update documentation for November 2021 provider's release (#19882)`` +`fe682ec3d3 `_ 2021-11-24 ``Fix duplicate changelog entries (#19759)`` +`0d60d1af41 `_ 2021-11-23 ``Checking event.status.container_statuses before filtering (#19713)`` +`1e57022953 `_ 2021-11-19 ``Added namespace as a template field in the KPO. (#19718)`` +`f7410dfba2 `_ 2021-11-19 ``Coalesce 'extra' params to None in KubernetesHook (#19694)`` +`bf5f452413 `_ 2021-11-08 ``Change to correct type in KubernetesPodOperator (#19459)`` +`854b70b904 `_ 2021-11-07 ``Decouple name randomization from name kwarg (#19398)`` +================================================================================================= =========== ====================================================================== + +2.1.0 +..... + +Latest change: 2021-10-29 + +================================================================================================= =========== ====================================================================== +Commit Committed Subject +================================================================================================= =========== ====================================================================== +`d9567eb106 `_ 2021-10-29 ``Prepare documentation for October Provider's release (#19321)`` +`0a6850647e `_ 2021-10-21 ``Update docstring to let users use 'node_selector' (#19057)`` +`1571f80546 `_ 2021-10-14 ``Add pre-commit hook for common misspelling check in files (#18964)`` +`b2045d6d1d `_ 2021-10-13 ``Add more type hints to PodLauncher (#18928)`` +`c8b86e69e4 `_ 2021-10-12 ``Add more information to PodLauncher timeout error (#17953)`` +================================================================================================= =========== ====================================================================== + +2.0.3 +..... + +Latest change: 2021-09-30 + +================================================================================================= =========== ====================================================================================== +Commit Committed Subject +================================================================================================= =========== ====================================================================================== +`840ea3efb9 `_ 2021-09-30 ``Update documentation for September providers release (#18613)`` +`ef037e7021 `_ 2021-09-29 ``Static start_date and default arg cleanup for misc. provider example DAGs (#18597)`` +`7808be7ffb `_ 2021-09-21 ``Make Kubernetes job description fit on one log line (#18377)`` +`b8d06e812a `_ 2021-09-08 ``Fix KubernetesPodOperator reattach when not deleting pods (#18070)`` +`64d2f5488f `_ 2021-09-07 ``Do not fail KubernetesPodOperator tasks if log reading fails (#17649)`` +`0a68588479 `_ 2021-08-30 ``Add August 2021 Provider's documentation (#17890)`` +`42e13e1a5a `_ 2021-08-30 ``Remove all deprecation warnings in providers (#17900)`` +================================================================================================= =========== ====================================================================================== + +2.0.2 +..... + +Latest change: 2021-08-24 + +================================================================================================= =========== ============================================================================ +Commit Committed Subject +================================================================================================= =========== ============================================================================ +`bb5602c652 `_ 2021-08-24 ``Prepare release for Kubernetes Provider (#17798)`` +`be75dcd39c `_ 2021-08-23 ``Update description about the new ''connection-types'' provider meta-data`` +`73d2b720e0 `_ 2021-08-21 ``Fix using XCom with ''KubernetesPodOperator'' (#17760)`` +`76ed2a49c6 `_ 2021-08-19 ``Import Hooks lazily individually in providers manager (#17682)`` +`97428efc41 `_ 2021-08-02 ``Fix messed-up changelog in 3 providers (#17380)`` +`b0b2591071 `_ 2021-07-27 ``Fix static checks (#17256)`` +`997f7d0beb `_ 2021-07-27 ``Update spark_kubernetes.py (#17237)`` +================================================================================================= =========== ============================================================================ + +2.0.1 +..... + +Latest change: 2021-07-26 + +================================================================================================= =========== ========================================================================================== +Commit Committed Subject +================================================================================================= =========== ========================================================================================== +`87f408b1e7 `_ 2021-07-26 ``Prepares docs for Rc2 release of July providers (#17116)`` +`d48b4e0caf `_ 2021-07-21 ``Simplify 'default_args' in Kubernetes example DAGs (#16870)`` +`3939e84161 `_ 2021-07-20 ``Enable using custom pod launcher in Kubernetes Pod Operator (#16945)`` +`d02ded65ea `_ 2021-07-15 ``Fixed wrongly escaped characters in amazon's changelog (#17020)`` +`b916b75079 `_ 2021-07-15 ``Prepare documentation for July release of providers. (#17015)`` +`b2c66e45b7 `_ 2021-07-11 ``BugFix: Using 'json' string in template_field causes issue with K8s Operators (#16930)`` +`9d6ae609b6 `_ 2021-06-28 ``Updating task dependencies (#16624)`` +`866a601b76 `_ 2021-06-28 ``Removes pylint from our toolchain (#16682)`` +================================================================================================= =========== ========================================================================================== + +2.0.0 +..... + +Latest change: 2021-06-18 + +================================================================================================= =========== =============================================================================================== +Commit Committed Subject +================================================================================================= =========== =============================================================================================== +`bbc627a3da `_ 2021-06-18 ``Prepares documentation for rc2 release of Providers (#16501)`` +`4c9735ff9b `_ 2021-06-17 ``Fix unsuccessful KubernetesPod final_state call when 'is_delete_operator_pod=True' (#15490)`` +`cbf8001d76 `_ 2021-06-16 ``Synchronizes updated changelog after buggfix release (#16464)`` +`1fba5402bb `_ 2021-06-15 ``More documentation update for June providers release (#16405)`` +`4752fb3eb8 `_ 2021-06-14 ``Fix issue with parsing error logs in the KPO (#15638)`` +`9c94b72d44 `_ 2021-06-07 ``Updated documentation for June 2021 provider release (#16294)`` +`2f16757e1a `_ 2021-06-03 ``Bug Pod Template File Values Ignored (#16095)`` +`476d0f6e3d `_ 2021-05-22 ``Bump pyupgrade v2.13.0 to v2.18.1 (#15991)`` +`85b2ccb0c5 `_ 2021-05-20 ``Add 'KubernetesPodOperat' 'pod-template-file' jinja template support (#15942)`` +`733bec9a04 `_ 2021-05-20 ``Bug Fix Pod-Template Affinity Ignored due to empty Affinity K8S Object (#15787)`` +`37d549bde7 `_ 2021-05-14 ``Save pod name to xcom for KubernetesPodOperator (#15755)`` +`37681bca00 `_ 2021-05-07 ``Auto-apply apply_default decorator (#15667)`` +================================================================================================= =========== =============================================================================================== + +1.2.0 +..... + +Latest change: 2021-05-01 + +================================================================================================= =========== =========================================================================== +Commit Committed Subject +================================================================================================= =========== =========================================================================== +`807ad32ce5 `_ 2021-05-01 ``Prepares provider release after PIP 21 compatibility (#15576)`` +`5b2fe0e740 `_ 2021-04-27 ``Add Connection Documentation for Popular Providers (#15393)`` +`53fc1a9679 `_ 2021-04-26 ``Change KPO node_selectors warning to proper deprecationwarning (#15507)`` +`d3cc67aa7a `_ 2021-04-24 ``Fix timeout when using XCom with KubernetesPodOperator (#15388)`` +`be421a6b07 `_ 2021-04-23 ``Fix labels on the pod created by ''KubernetsPodOperator'' (#15492)`` +`44480d3673 `_ 2021-04-14 ``Require 'name' with KubernetesPodOperator (#15373)`` +`b4770725a3 `_ 2021-04-12 ``Add links to new modules for deprecated modules (#15316)`` +================================================================================================= =========== =========================================================================== + +1.1.0 +..... + +Latest change: 2021-04-07 + +================================================================================================= =========== ============================================================================= +Commit Committed Subject +================================================================================================= =========== ============================================================================= +`1806670383 `_ 2021-04-07 ``Retry pod launching on 409 ApiExceptions (#15137)`` +`042be2e4e0 `_ 2021-04-06 ``Updated documentation for provider packages before April release (#15236)`` +`6d7a70b88e `_ 2021-04-05 ``Separate Kubernetes pod_launcher from core airflow (#15165)`` +`00453dc4a2 `_ 2021-03-20 ``Add ability to specify api group and version for Spark operators (#14898)`` +`68e4c4dcb0 `_ 2021-03-20 ``Remove Backport Providers (#14886)`` +`e7bb17aeb8 `_ 2021-03-06 ``Use built-in 'cached_property' on Python 3.8 where possible (#14606)`` +`7daebefd15 `_ 2021-03-05 ``Use libyaml C library when available. (#14577)`` +================================================================================================= =========== ============================================================================= + +1.0.2 +..... + +Latest change: 2021-02-27 + +================================================================================================= =========== ============================================================================ +Commit Committed Subject +================================================================================================= =========== ============================================================================ +`589d6dec92 `_ 2021-02-27 ``Prepare to release the next wave of providers: (#14487)`` +`809b4f9b18 `_ 2021-02-23 ``Unique pod name (#14186)`` +`649335c043 `_ 2021-02-07 ``Template k8s.V1EnvVar without adding custom attributes to dict. (#14123)`` +`d4c4db8a18 `_ 2021-02-05 ``Allow users of the KPO to template environment variables (#14083)`` +`10343ec29f `_ 2021-02-05 ``Corrections in docs and tools after releasing provider RCs (#14082)`` +================================================================================================= =========== ============================================================================ + +1.0.1 +..... + +Latest change: 2021-02-04 + +================================================================================================= =========== ========================================================================================== +Commit Committed Subject +================================================================================================= =========== ========================================================================================== +`88bdcfa0df `_ 2021-02-04 ``Prepare to release a new wave of providers. (#14013)`` +`ac2f72c98d `_ 2021-02-01 ``Implement provider versioning tools (#13767)`` +`a9ac2b040b `_ 2021-01-23 ``Switch to f-strings using flynt. (#13732)`` +`1b9e3d1c28 `_ 2021-01-22 ``Revert "Fix error with quick-failing tasks in KubernetesPodOperator (#13621)" (#13835)`` +`94d3ed61d6 `_ 2021-01-21 ``Fix error with quick-failing tasks in KubernetesPodOperator (#13621)`` +`3fd5ef3555 `_ 2021-01-21 ``Add missing logos for integrations (#13717)`` +`295d66f914 `_ 2020-12-30 ``Fix Grammar in PIP warning (#13380)`` +`7a560ab6de `_ 2020-12-24 ``Pass image_pull_policy in KubernetesPodOperator correctly (#13289)`` +`6cf76d7ac0 `_ 2020-12-18 ``Fix typo in pip upgrade command :( (#13148)`` +================================================================================================= =========== ========================================================================================== + +1.0.0 +..... + +Latest change: 2020-12-09 + +================================================================================================= =========== ================================================================================================ +Commit Committed Subject +================================================================================================= =========== ================================================================================================ +`32971a1a2d `_ 2020-12-09 ``Updates providers versions to 1.0.0 (#12955)`` +`b40dffa085 `_ 2020-12-08 ``Rename remaing modules to match AIP-21 (#12917)`` +`9b39f24780 `_ 2020-12-08 ``Add support for dynamic connection form fields per provider (#12558)`` +`bd90136aaf `_ 2020-11-30 ``Move operator guides to provider documentation packages (#12681)`` +`2037303eef `_ 2020-11-29 ``Adds support for Connection/Hook discovery from providers (#12466)`` +`de3b1e687b `_ 2020-11-28 ``Move connection guides to provider documentation packages (#12653)`` +`c02a3f59e4 `_ 2020-11-23 ``Spark-on-k8s sensor logs - properly pass defined namespace to pod log call (#11199)`` +`c34ef853c8 `_ 2020-11-20 ``Separate out documentation building per provider (#12444)`` +`9e089ab895 `_ 2020-11-19 ``Fix Kube tests (#12479)`` +`d32fe78c0d `_ 2020-11-18 ``Update readmes for cncf.kube provider fixes (#12457)`` +`d84a52dc8f `_ 2020-11-18 ``Fix broken example_kubernetes DAG (#12455)`` +`7c8b71d201 `_ 2020-11-18 ``Fix backwards compatibility further (#12451)`` +`0080354502 `_ 2020-11-18 ``Update provider READMEs for 1.0.0b2 batch release (#12449)`` +`7ca0b6f121 `_ 2020-11-18 ``Enable Markdownlint rule MD003/heading-style/header-style (#12427) (#12438)`` +`763b40d223 `_ 2020-11-18 ``Raise correct Warning in kubernetes/backcompat/volume_mount.py (#12432)`` +`bc4bb30588 `_ 2020-11-18 ``Fix docstrings for Kubernetes Backcompat module (#12422)`` +`cab86d80d4 `_ 2020-11-17 ``Make K8sPodOperator backwards compatible (#12384)`` +`ae7cb4a1e2 `_ 2020-11-17 ``Update wrong commit hash in backport provider changes (#12390)`` +`6889a333cf `_ 2020-11-15 ``Improvements for operators and hooks ref docs (#12366)`` +`221f809c1b `_ 2020-11-14 ``Fix full_pod_spec for k8spodoperator (#12354)`` +`7825e8f590 `_ 2020-11-13 ``Docs installation improvements (#12304)`` +`85a18e13d9 `_ 2020-11-09 ``Point at pypi project pages for cross-dependency of provider packages (#12212)`` +`59eb5de78c `_ 2020-11-09 ``Update provider READMEs for up-coming 1.0.0beta1 releases (#12206)`` +`3f59e75cdf `_ 2020-11-09 ``KubernetesPodOperator: use randomized name to get the failure status (#12171)`` +`b2a28d1590 `_ 2020-11-09 ``Moves provider packages scripts to dev (#12082)`` +`7825be50d8 `_ 2020-11-05 ``Randomize pod name (#12117)`` +`91a64db505 `_ 2020-11-04 ``Format all files (without excepions) by black (#12091)`` +`4e8f9cc8d0 `_ 2020-11-03 ``Enable Black - Python Auto Formmatter (#9550)`` +`8c42cf1b00 `_ 2020-11-03 ``Use PyUpgrade to use Python 3.6 features (#11447)`` +`5a439e84eb `_ 2020-10-26 ``Prepare providers release 0.0.2a1 (#11855)`` +`872b1566a1 `_ 2020-10-25 ``Generated backport providers readmes/setup for 2020.10.29 (#11826)`` +`53e6062105 `_ 2020-10-21 ``Enforce strict rules for yamllint (#11709)`` +`349b0811c3 `_ 2020-10-20 ``Add D200 pydocstyle check (#11688)`` +`eee4e30f2c `_ 2020-10-15 ``Add better debug logging to K8sexec and K8sPodOp (#11502)`` +`16e7129719 `_ 2020-10-13 ``Added support for provider packages for Airflow 2.0 (#11487)`` +`8640fb6c10 `_ 2020-10-09 ``fix tests (#11368)`` +`298052fcee `_ 2020-10-10 ``[airflow/providers/cncf/kubernetes] correct hook methods name (#11008)`` +`49aad025b5 `_ 2020-10-09 ``Users can specify sub-secrets and paths k8spodop (#11369)`` +`b93b6c5be3 `_ 2020-10-05 ``Allow labels in KubernetesPodOperator to be templated (#10796)`` +`0a0e1af800 `_ 2020-10-03 ``Fix Broken Markdown links in Providers README TOC (#11249)`` +`ca4238eb4d `_ 2020-10-02 ``Fixed month in backport packages to October (#11242)`` +`5220e4c384 `_ 2020-10-02 ``Prepare Backport release 2020.09.07 (#11238)`` +`a888198c27 `_ 2020-09-27 ``Allow overrides for pod_template_file (#11162)`` +`0161b5ea2b `_ 2020-09-26 ``Increasing type coverage for multiple provider (#11159)`` +`e3f96ce7a8 `_ 2020-09-24 ``Fix incorrect Usage of Optional[bool] (#11138)`` +`f3e87c5030 `_ 2020-09-22 ``Add D202 pydocstyle check (#11032)`` +`b61225a885 `_ 2020-09-21 ``Add D204 pydocstyle check (#11031)`` +`cba51d49ee `_ 2020-09-17 ``Simplify the K8sExecutor and K8sPodOperator (#10393)`` +`1294e15d44 `_ 2020-09-16 ``KubernetesPodOperator template fix (#10963)`` +`5d6d5a2f7d `_ 2020-09-14 ``Allow to specify path to kubeconfig in KubernetesHook (#10453)`` +`7edfac957b `_ 2020-09-09 ``Add connection caching to KubernetesHook (#10447)`` +`9549274d11 `_ 2020-09-09 ``Upgrade black to 20.8b1 (#10818)`` +`90c1505686 `_ 2020-09-04 ``Make grace_period_seconds option on K8sPodOperator (#10727)`` +`338b412c04 `_ 2020-09-02 ``Add on_kill support for the KubernetesPodOperator (#10666)`` +`596bc13379 `_ 2020-08-31 ``Adds 'cncf.kubernetes' package back to backport provider packages. (#10659)`` +`1e5aa4465c `_ 2020-08-26 ``Spark-on-K8S sensor - add driver logs (#10023)`` +`fdd9b6f65b `_ 2020-08-25 ``Enable Black on Providers Packages (#10543)`` +`2f2d8dbfaf `_ 2020-08-25 ``Remove all "noinspection" comments native to IntelliJ (#10525)`` +`7c206a82a6 `_ 2020-08-22 ``Replace assigment with Augmented assignment (#10468)`` +`8cd2be9e16 `_ 2020-08-11 ``Fix KubernetesPodOperator reattachment (#10230)`` +`cdec301254 `_ 2020-08-07 ``Add correct signature to all operators and sensors (#10205)`` +`24c8e4c2d6 `_ 2020-08-06 ``Changes to all the constructors to remove the args argument (#10163)`` +`aeea71274d `_ 2020-08-02 ``Remove 'args' parameter from provider operator constructors (#10097)`` +`f1fd3e2c45 `_ 2020-07-31 ``Fix typo on reattach property of kubernetespodoperator (#10056)`` +`03c4351744 `_ 2020-07-31 ``Allow 'image' in 'KubernetesPodOperator' to be templated (#10068)`` +`88c1603060 `_ 2020-07-31 ``Improve docstring note about GKEStartPodOperator on KubernetesPodOperator (#10049)`` +`7d24b088cd `_ 2020-07-25 ``Stop using start_date in default_args in example_dags (2) (#9985)`` +`33f0cd2657 `_ 2020-07-22 ``apply_default keeps the function signature for mypy (#9784)`` +`c2db0dfeb1 `_ 2020-07-22 ``More strict rules in mypy (#9705) (#9906)`` +`719ae2bf62 `_ 2020-07-22 ``Dump Pod as YAML in logs for KubernetesPodOperator (#9895)`` +`840799d559 `_ 2020-07-20 ``Improve KubernetesPodOperator guide (#9079)`` +`44d4ae809c `_ 2020-07-06 ``Upgrade to latest pre-commit checks (#9686)`` +`8bd15ef634 `_ 2020-07-01 ``Switches to Helm Chart for Kubernetes tests (#9468)`` +`40bf8f28f9 `_ 2020-06-18 ``Detect automatically the lack of reference to the guide in the operator descriptions (#9290)`` +`1d36b0303b `_ 2020-05-23 ``Fix references in docs (#8984)`` +`e742ef7c70 `_ 2020-05-23 ``Fix typo in test_project_structure (#8978)`` +`375d1ca229 `_ 2020-05-19 ``Release candidate 2 for backport packages 2020.05.20 (#8898)`` +`12c5e5d8ae `_ 2020-05-17 ``Prepare release candidate for backport packages (#8891)`` +`8985df0bfc `_ 2020-05-16 ``Monitor pods by labels instead of names (#6377)`` +`f3521fb0e3 `_ 2020-05-16 ``Regenerate readme files for backport package release (#8886)`` +`92585ca4cb `_ 2020-05-15 ``Added automated release notes generation for backport operators (#8807)`` +`f82ad452b0 `_ 2020-05-15 ``Fix KubernetesPodOperator pod name length validation (#8829)`` +`1ccafc617c `_ 2020-04-02 ``Add spark_kubernetes system test (#7875)`` +`cd546b664f `_ 2020-03-23 ``Add missing call to Super class in 'cncf' & 'docker' providers (#7825)`` +`6c39a3bf97 `_ 2020-03-10 ``[AIRFLOW-6542] Add spark-on-k8s operator/hook/sensor (#7163)`` +`42eef38217 `_ 2020-03-07 ``[AIRFLOW-6877] Add cross-provider dependencies as extras (#7506)`` +`3320e432a1 `_ 2020-02-24 ``[AIRFLOW-6817] Lazy-load 'airflow.DAG' to keep user-facing API untouched (#7517)`` +`0ec2774120 `_ 2020-02-24 ``[AIRFLOW-5629] Implement Kubernetes priorityClassName in KubernetesPodOperator (#7395)`` +`9cbd7de6d1 `_ 2020-02-18 ``[AIRFLOW-6792] Remove _operator/_hook/_sensor in providers package and add tests (#7412)`` +`967930c0cb `_ 2020-02-11 ``[AIRFLOW-5413] Allow K8S worker pod to be configured from JSON/YAML file (#6230)`` +`96f834389e `_ 2020-02-03 ``[AIRFLOW-6678] Pull event logs from Kubernetes (#7292)`` +`97a429f9d0 `_ 2020-02-02 ``[AIRFLOW-6714] Remove magic comments about UTF-8 (#7338)`` +`cf141506a2 `_ 2020-02-02 ``[AIRFLOW-6708] Set unique logger names (#7330)`` +`373c6aa4a2 `_ 2020-01-30 ``[AIRFLOW-6682] Move GCP classes to providers package (#7295)`` +`83c037873f `_ 2020-01-30 ``[AIRFLOW-6674] Move example_dags in accordance with AIP-21 (#7287)`` +`059eda05f8 `_ 2020-01-21 ``[AIRFLOW-6610] Move software classes to providers package (#7231)`` +================================================================================================= =========== ================================================================================================ diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/configurations-ref.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/configurations-ref.rst.txt new file mode 100644 index 00000000000..5885c9d91b6 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/configurations-ref.rst.txt @@ -0,0 +1,18 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +.. include:: ../exts/includes/providers-configurations-ref.rst diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/connections/kubernetes.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/connections/kubernetes.rst.txt new file mode 100644 index 00000000000..cb1caa4b634 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/connections/kubernetes.rst.txt @@ -0,0 +1,84 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +.. _howto/connection:kubernetes: + +Kubernetes cluster Connection +============================= + +The Kubernetes cluster Connection type enables connection to a Kubernetes cluster by :class:`~airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator` tasks and :class:`~airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator` tasks. + + +Authenticating to Kubernetes cluster +------------------------------------ + +There are different ways to connect to Kubernetes using Airflow. + +#. Use kube_config that reside in the default location on the machine(~/.kube/config) - just leave all fields empty +#. Use in_cluster config, if Airflow runs inside Kubernetes cluster take the configuration from the cluster - mark: + In cluster configuration +#. Use kube_config from different location - insert the path into ``Kube config path`` +#. Use kube_config in JSON format from connection configuration - paste kube_config into ``Kube config (JSON format)`` + + +Default Connection IDs +---------------------- + +The default connection ID is ``kubernetes_default`` . + +Configuring the Connection +-------------------------- + + +In cluster configuration + Use in cluster configuration. + +Kube config path + Use custom path to kube config. + +Kube config (JSON format) + `Kube config `_ + that used to connect to Kubernetes client. + +Namespace + Default Kubernetes namespace for the connection. + +Cluster context + When using a kube config, can specify which context to use. + +Disable verify SSL + Can optionally disable SSL certificate verification. By default SSL is verified. + +Disable TCP keepalive + TCP keepalive is a feature (enabled by default) that tries to keep long-running connections + alive. Set this parameter to True to disable this feature. + +Xcom sidecar image + Define the ``image`` used by the ``PodDefaults.SIDECAR_CONTAINER`` (defaults to ``"alpine"``) to allow private + repositories, as well as custom image overrides. + +Example storing connection in env var using URI format: + +.. code-block:: bash + + AIRFLOW_CONN_KUBERNETES_DEFAULT='kubernetes://?in_cluster=True&kube_config_path=~%2F.kube%2Fconfig&kube_config=kubeconfig+json&namespace=namespace' + +And using JSON format: + +.. code-block:: bash + + AIRFLOW_CONN_KUBERNETES_DEFAULT='{"conn_type": "kubernetes", "extra": {"in_cluster": true, "kube_config_path": "~/.kube/config", "namespace": "my-namespace"}}' diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/index.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/index.rst.txt new file mode 100644 index 00000000000..b7d8bc5ffb0 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/index.rst.txt @@ -0,0 +1,120 @@ + + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +``apache-airflow-providers-cncf-kubernetes`` +============================================ + + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: Basics + + Home + Changelog + Security + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: Executors + + KubernetesExecutor details + LocalKubernetesExecutor details + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: Guides + + Connection types + Operators + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: References + + Configuration + CLI + Python API <_api/airflow/providers/cncf/kubernetes/index> + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: System tests + + System Tests <_api/tests/system/providers/cncf/kubernetes/index> + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: Resources + + Example DAGs + PyPI Repository + Installing from sources + +.. THE REMAINDER OF THE FILE IS AUTOMATICALLY GENERATED. IT WILL BE OVERWRITTEN AT RELEASE TIME! + + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: Commits + + Detailed list of commits + + +apache-airflow-providers-cncf-kubernetes package +------------------------------------------------------ + +`Kubernetes `__ + + +Release: 8.1.1 + +Provider package +---------------- + +This package is for the ``cncf.kubernetes`` provider. +All classes for this package are included in the ``airflow.providers.cncf.kubernetes`` python package. + +Installation +------------ + +You can install this package on top of an existing Airflow 2 installation via +``pip install apache-airflow-providers-cncf-kubernetes``. +For the minimum Airflow version supported, see ``Requirements`` below. + +Requirements +------------ + +The minimum Apache Airflow version supported by this provider package is ``2.6.0``. + +====================== ===================== +PIP package Version required +====================== ===================== +``aiofiles`` ``>=23.2.0`` +``apache-airflow`` ``>=2.6.0`` +``asgiref`` ``>=3.5.2`` +``cryptography`` ``>=2.0.0`` +``kubernetes`` ``>=28.1.0,<=29.0.0`` +``kubernetes_asyncio`` ``>=28.1.0,<=29.0.0`` +``google-re2`` ``>=1.0`` +====================== ===================== diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/installing-providers-from-sources.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/installing-providers-from-sources.rst.txt new file mode 100644 index 00000000000..b4e730f4ff2 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/installing-providers-from-sources.rst.txt @@ -0,0 +1,18 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +.. include:: ../exts/includes/installing-providers-from-sources.rst diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/kubernetes_executor.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/kubernetes_executor.rst.txt new file mode 100644 index 00000000000..5662d7a0e1f --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/kubernetes_executor.rst.txt @@ -0,0 +1,290 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + +.. _KubernetesExecutor: + +Kubernetes Executor +=================== + +.. note:: + + As of Airflow 2.7.0, you need to install the ``cncf.kubernetes`` provider package to use + this executor. This can done by installing ``apache-airflow-providers-cncf-kubernetes>=7.4.0`` + or by installing Airflow with the ``cncf.kubernetes`` extras: + ``pip install 'apache-airflow[cncf.kubernetes]'``. + + +The Kubernetes executor runs each task instance in its own pod on a Kubernetes cluster. + +KubernetesExecutor runs as a process in the Airflow Scheduler. The scheduler itself does +not necessarily need to be running on Kubernetes, but does need access to a Kubernetes cluster. + +KubernetesExecutor requires a non-sqlite database in the backend. + +When a DAG submits a task, the KubernetesExecutor requests a worker pod from the Kubernetes API. The worker pod then runs the task, reports the result, and terminates. + +.. image:: img/arch-diag-kubernetes.png + + +One example of an Airflow deployment running on a distributed set of five nodes in a Kubernetes cluster is shown below. + +.. image:: img/arch-diag-kubernetes2.png + +Consistent with the regular Airflow architecture, the Workers need access to the DAG files to execute the tasks within those DAGs and interact with the Metadata repository. Also, configuration information specific to the Kubernetes Executor, such as the worker namespace and image information, needs to be specified in the Airflow Configuration file. + +Additionally, the Kubernetes Executor enables specification of additional features on a per-task basis using the Executor config. + +.. @startuml +.. Airflow_Scheduler -> Kubernetes: Request a new pod with command "airflow run..." +.. Kubernetes -> Airflow_Worker: Create Airflow worker with command "airflow run..." +.. Airflow_Worker -> Airflow_DB: Report task passing or failure to DB +.. Airflow_Worker -> Kubernetes: Pod completes with state "Succeeded" and k8s records in ETCD +.. Kubernetes -> Airflow_Scheduler: Airflow scheduler reads "Succeeded" from k8s watcher thread +.. @enduml +.. image:: img/k8s-happy-path.png + +Configuration +------------- + +.. _concepts:pod_template_file: + +pod_template_file +~~~~~~~~~~~~~~~~~ + +To customize the pod used for k8s executor worker processes, you may create a pod template file. You must provide +the path to the template file in the ``pod_template_file`` option in the ``kubernetes_executor`` section of ``airflow.cfg``. + +Airflow has two strict requirements for pod template files: base image and pod name. + +Base image +^^^^^^^^^^ + +A ``pod_template_file`` must have a container named ``base`` at the ``spec.containers[0]`` position, and +its ``image`` must be specified. + +You are free to create sidecar containers after this required container, but Airflow assumes that the +airflow worker container exists at the beginning of the container array, and assumes that the +container is named ``base``. + +.. note:: + + Airflow may override the base container ``image``, e.g. through :ref:`pod_override ` + configuration; but it must be present in the template file and must not be blank. + +Pod name +^^^^^^^^ + +The pod's ``metadata.name`` must be set in the template file. This field will *always* be set dynamically at +pod launch to guarantee uniqueness across all pods. But again, it must be included in the template, and cannot +be left blank. + + +Example pod templates +~~~~~~~~~~~~~~~~~~~~~ + +With these requirements in mind, here are some examples of basic ``pod_template_file`` YAML files. + +.. note:: + + The examples below should work when using default Airflow configuration values. However, many custom + configuration values need to be explicitly passed to the pod via this template too. This includes, + but is not limited to, sql configuration, required Airflow connections, DAGs folder path and + logging settings. See :doc:`../../configurations-ref` for details. + +Storing DAGs in the image: + +.. literalinclude:: /../../airflow/providers/cncf/kubernetes/pod_template_file_examples/dags_in_image_template.yaml + :language: yaml + :start-after: [START template_with_dags_in_image] + :end-before: [END template_with_dags_in_image] + +Storing DAGs in a ``persistentVolume``: + +.. literalinclude:: /../../airflow/providers/cncf/kubernetes/pod_template_file_examples/dags_in_volume_template.yaml + :language: yaml + :start-after: [START template_with_dags_in_volume] + :end-before: [END template_with_dags_in_volume] + +Pulling DAGs from ``git``: + +.. literalinclude:: /../../airflow/providers/cncf/kubernetes/pod_template_file_examples/git_sync_template.yaml + :language: yaml + :start-after: [START git_sync_template] + :end-before: [END git_sync_template] + +.. _concepts:pod_override: + +pod_override +~~~~~~~~~~~~ + +When using the KubernetesExecutor, Airflow offers the ability to override system defaults on a per-task basis. +To utilize this functionality, create a Kubernetes V1pod object and fill in your desired overrides. +Please note that the scheduler will override the ``metadata.name`` and ``containers[0].args`` of the V1pod before launching it. + +To overwrite the base container of the pod launched by the KubernetesExecutor, +create a V1pod with a single container, and overwrite the fields as follows: + +.. exampleinclude:: /../../airflow/example_dags/example_kubernetes_executor.py + :language: python + :start-after: [START task_with_volume] + :end-before: [END task_with_volume] + +Note that the following fields **will all be extended** instead of overwritten. From *spec*: volumes, and init_containers. From *container*: volume mounts, environment variables, ports, and devices. + +To add a sidecar container to the launched pod, create a V1pod with an empty first container with the +name ``base`` and a second container containing your desired sidecar. + +.. exampleinclude:: /../../airflow/example_dags/example_kubernetes_executor.py + :language: python + :start-after: [START task_with_sidecar] + :end-before: [END task_with_sidecar] + +You can also create custom ``pod_template_file`` on a per-task basis so that you can recycle the same base values between multiple tasks. +This will replace the default ``pod_template_file`` named in the airflow.cfg and then override that template using the ``pod_override``. + +Here is an example of a task with both features: + +.. code-block:: python + + import os + + import pendulum + + from airflow import DAG + from airflow.decorators import task + from airflow.example_dags.libs.helper import print_stuff + from airflow.settings import AIRFLOW_HOME + + from kubernetes.client import models as k8s + + with DAG( + dag_id="example_pod_template_file", + schedule=None, + start_date=pendulum.datetime(2021, 1, 1, tz="UTC"), + catchup=False, + tags=["example3"], + ) as dag: + executor_config_template = { + "pod_template_file": os.path.join(AIRFLOW_HOME, "pod_templates/basic_template.yaml"), + "pod_override": k8s.V1Pod(metadata=k8s.V1ObjectMeta(labels={"release": "stable"})), + } + + @task(executor_config=executor_config_template) + def task_with_template(): + print_stuff() + + +Managing DAGs and logs +~~~~~~~~~~~~~~~~~~~~~~ + +Use of persistent volumes is optional and depends on your configuration. + +- **Dags**: + +To get the DAGs into the workers, you can: + + - Include DAGs in the image. + - Use ``git-sync`` which, before starting the worker container, will run a ``git pull`` of the DAGs repository. + - Storing DAGs on a persistent volume, which can be mounted on all workers. + +- **Logs**: + +To get task logs out of the workers, you can: + + - Use a persistent volume mounted on both the webserver and workers. + + - Enable remote logging. + +.. note:: + + If you don't enable logging persistence, and if you have not enabled remote logging, logs will be lost after the worker pods shut down. + + +Comparison with CeleryExecutor +------------------------------ + +In contrast to CeleryExecutor, KubernetesExecutor does not require additional components such as Redis, +but does require access to Kubernetes cluster. + +Also monitoring the Pods can be done with the built-in Kubernetes monitoring. + +With KubernetesExecutor, each task runs in its own pod. The pod is created when the task is queued, and terminates when the task completes. +Historically, in scenarios such as burstable workloads, this presented a resource utilization advantage over CeleryExecutor, where you needed +a fixed number of long-running Celery worker pods, whether or not there were tasks to run. + +However, the :doc:`official Apache Airflow Helm chart ` can automatically scale celery workers down to zero based on the number of tasks in the queue, +so when using the official chart, this is no longer an advantage. + +With Celery workers you will tend to have less task latency because the worker pod is already up and running when the task is queued. On the +other hand, because multiple tasks are running in the same pod, with Celery you may have to be more mindful about resource utilization +in your task design, particularly memory consumption. + +One scenario where KubernetesExecutor can be helpful is if you have long-running tasks, because if you deploy while a task is running, +the task will keep running until it completes (or times out, etc). But with CeleryExecutor, provided you have set a grace period, the +task will only keep running up until the grace period has elapsed, at which time the task will be terminated. Another scenario where +KubernetesExecutor can work well is when your tasks are not very uniform with respect to resource requirements or images. + +Finally, note that it does not have to be either-or; with CeleryKubernetesExecutor, it is possible to use both CeleryExecutor and +KubernetesExecutor simultaneously on the same cluster. CeleryKubernetesExecutor will look at a task's ``queue`` to determine +whether to run on Celery or Kubernetes. By default, tasks are sent to Celery workers, but if you want a task to run using KubernetesExecutor, +you send it to the ``kubernetes`` queue and it will run in its own pod. And KubernetesPodOperator can be used +to similar effect, no matter what executor you are using. + +Fault Tolerance +--------------- + +.. tip:: + + To troubleshoot issues with KubernetesExecutor, you can use ``airflow kubernetes generate-dag-yaml`` command. + This command generates the pods as they will be launched in Kubernetes and dumps them into yaml files for you to inspect. + + +Handling Worker Pod Crashes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When dealing with distributed systems, we need a system that assumes that any component can crash at any moment for reasons ranging from OOM errors to node upgrades. + +In the case where a worker dies before it can report its status to the backend DB, the executor can use a Kubernetes watcher thread to discover the failed pod. + +.. @startuml +.. +.. Airflow_Scheduler -> Kubernetes: Request a new pod with command "airflow run..." +.. Kubernetes -> Airflow_Worker: Create Airflow worker with command "airflow run..." +.. Airflow_Worker -> Airflow_Worker: Pod fails before task can complete +.. Airflow_Worker -> Kubernetes: Pod completes with state "Failed" and k8s records in ETCD +.. Kubernetes -> Airflow_Scheduler: Airflow scheduler reads "Failed" from k8s watcher thread +.. Airflow_Scheduler -> Airflow_DB: Airflow scheduler records "FAILED" state to DB for task +.. +.. @enduml + +.. image:: img/k8s-failed-pod.png + + +A Kubernetes watcher is a thread that can subscribe to every change that occurs in Kubernetes' database. It is alerted when pods start, run, end, and fail. +By monitoring this stream, the KubernetesExecutor can discover that the worker crashed and correctly report the task as failed. + + +But What About Cases Where the Scheduler Pod Crashes? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In cases of scheduler crashes, the scheduler will recover its state using the watcher's ``resourceVersion``. + +When monitoring the Kubernetes cluster's watcher thread, each event has a monotonically rising number called a ``resourceVersion``. +Every time the executor reads a ``resourceVersion``, the executor stores the latest value in the backend database. +Because the resourceVersion is stored, the scheduler can restart and continue reading the watcher stream from where it left off. +Since the tasks are run independently of the executor and report results directly to the database, scheduler failures will not lead to task failures or re-runs. diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/local_kubernetes_executor.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/local_kubernetes_executor.rst.txt new file mode 100644 index 00000000000..daed3d4d1f2 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/local_kubernetes_executor.rst.txt @@ -0,0 +1,37 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + +.. _LocalKubernetesExecutor: + +LocalKubernetes Executor +========================= + +.. note:: + + As of Airflow 2.7.0, you need to install the ``cncf.kubernetes`` provider package to use + this executor. This can be done by installing ``apache-airflow-providers-cncf-kubernetes>=7.4.0`` + or by installing Airflow with the ``cncf.kubernetes`` extras: + ``pip install 'apache-airflow[cncf.kubernetes]'``. + +The :class:`~airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor` allows users +to simultaneously run a ``LocalExecutor`` and a ``KubernetesExecutor``. +An executor is chosen to run a task based on the task's queue. + +``LocalKubernetesExecutor`` provides the capability of running tasks with either ``LocalExecutor``, +which runs tasks within the scheduler service, or with ``KubernetesExecutor``, which runs each task +in its own pod on a kubernetes cluster. diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/operators.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/operators.rst.txt new file mode 100644 index 00000000000..80541f315c0 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/operators.rst.txt @@ -0,0 +1,669 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + +.. contents:: Table of Contents + :depth: 2 + +.. _howto/operator:kubernetespodoperator: + +KubernetesPodOperator +===================== + +The :class:`~airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator` allows +you to create and run Pods on a Kubernetes cluster. + +.. note:: + If you use a managed Kubernetes consider using a specialize KPO operator as it simplifies the Kubernetes authorization process : + + - :ref:`GKEStartPodOperator ` operator for `Google Kubernetes Engine `__, + + - :ref:`EksPodOperator ` operator for `AWS Elastic Kubernetes Engine `__. + +.. note:: + The :doc:`Kubernetes executor ` is **not** required to use this operator. + +How does this operator work? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The :class:`~airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator` uses the +Kubernetes API to launch a pod in a Kubernetes cluster. By supplying an +image URL and a command with optional arguments, the operator uses the Kube Python Client to generate a Kubernetes API +request that dynamically launches those individual pods. +Users can specify a kubeconfig file using the ``config_file`` parameter, otherwise the operator will default +to ``~/.kube/config``. + +The :class:`~airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator` enables task-level +resource configuration and is optimal for custom Python +dependencies that are not available through the public PyPI repository. It also allows users to supply a template +YAML file using the ``pod_template_file`` parameter. +Ultimately, it allows Airflow to act a job orchestrator - no matter the language those jobs are written in. + +Debugging KubernetesPodOperator +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can print out the Kubernetes manifest for the pod that would be created at runtime by calling +:meth:`~.KubernetesPodOperator.dry_run` on an instance of the operator. + +.. code-block:: python + + from airflow.providers.cncf.kubernetes.operators.pod import KubernetesPodOperator + + k = KubernetesPodOperator( + name="hello-dry-run", + image="debian", + cmds=["bash", "-cx"], + arguments=["echo", "10"], + labels={"foo": "bar"}, + task_id="dry_run_demo", + do_xcom_push=True, + ) + + k.dry_run() + +Argument precedence +^^^^^^^^^^^^^^^^^^^ + +When KPO defines the pod object, there may be overlap between the :class:`~airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator` arguments. +In general, the order of precedence is KPO field-specific arguments (e.g., ``secrets``, ``cmds``, ``affinity``), more general templates ``full_pod_spec``, ``pod_template_file``, ``pod_template_dict``, and followed by ``V1Pod``, by default. + +For ``namespace``, if namespace is not provided via any of these methods, then we'll first try to +get the current namespace (if the task is already running in kubernetes) and failing that we'll use +the ``default`` namespace. + +For pod name, if not provided explicitly, we'll use the task_id. A random suffix is added by default so the pod +name is not generally of great consequence. + +How to use cluster ConfigMaps, Secrets, and Volumes with Pod? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To add ConfigMaps, Volumes, and other Kubernetes native objects, we recommend that you import the Kubernetes model API +like this: + +.. code-block:: python + + from kubernetes.client import models as k8s + +With this API object, you can have access to all Kubernetes API objects in the form of python classes. +Using this method will ensure correctness +and type safety. While we have removed almost all Kubernetes convenience classes, we have kept the +:class:`~airflow.providers.cncf.kubernetes.secret.Secret` class to simplify the process of generating secret volumes/env variables. + +.. exampleinclude:: /../../tests/system/providers/cncf/kubernetes/example_kubernetes.py + :language: python + :start-after: [START howto_operator_k8s_cluster_resources] + :end-before: [END howto_operator_k8s_cluster_resources] + +Difference between ``KubernetesPodOperator`` and Kubernetes object spec +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The :class:`~airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator` can be considered +a substitute for a Kubernetes object spec definition that is able +to be run in the Airflow scheduler in the DAG context. If using the operator, there is no need to create the +equivalent YAML/JSON object spec for the Pod you would like to run. +The YAML file can still be provided with the ``pod_template_file`` or even the Pod Spec constructed in Python via +the ``full_pod_spec`` parameter which requires a Kubernetes ``V1Pod``. + +How to use private images (container registry)? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, the :class:`~airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator` will +look for images hosted publicly on Dockerhub. +To pull images from a private registry (such as ECR, GCR, Quay, or others), you must create a +Kubernetes Secret that represents the credentials for accessing images from the private registry that is ultimately +specified in the ``image_pull_secrets`` parameter. + +Create the Secret using ``kubectl``: + +.. code-block:: none + + kubectl create secret docker-registry testquay \ + --docker-server=quay.io \ + --docker-username= \ + --docker-password= + +Then use it in your pod like so: + +.. exampleinclude:: /../../tests/system/providers/cncf/kubernetes/example_kubernetes.py + :language: python + :start-after: [START howto_operator_k8s_private_image] + :end-before: [END howto_operator_k8s_private_image] + +Also for this action you can use operator in the deferrable mode: + +.. exampleinclude:: /../../tests/system/providers/cncf/kubernetes/example_kubernetes_async.py + :language: python + :start-after: [START howto_operator_k8s_private_image_async] + :end-before: [END howto_operator_k8s_private_image_async] + +Example to fetch and display container log periodically + +.. exampleinclude:: /../../tests/system/providers/cncf/kubernetes/example_kubernetes_async.py + :language: python + :start-after: [START howto_operator_async_log] + :end-before: [END howto_operator_async_log] + + +How does XCom work? +^^^^^^^^^^^^^^^^^^^ +The :class:`~airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator` handles +XCom values differently than other operators. In order to pass a XCom value +from your Pod you must specify the ``do_xcom_push`` as ``True``. This will create a sidecar container that runs +alongside the Pod. The Pod must write the XCom value into this location at the ``/airflow/xcom/return.json`` path. + +.. note:: + An invalid json content will fail, example ``echo 'hello' > /airflow/xcom/return.json`` fail and ``echo '\"hello\"' > /airflow/xcom/return.json`` work + + +See the following example on how this occurs: + +.. exampleinclude:: /../../tests/system/providers/cncf/kubernetes/example_kubernetes.py + :language: python + :start-after: [START howto_operator_k8s_write_xcom] + :end-before: [END howto_operator_k8s_write_xcom] +.. note:: + XCOMs will be pushed only for tasks marked as ``State.SUCCESS``. + +Also for this action you can use operator in the deferrable mode: + +.. exampleinclude:: /../../tests/system/providers/cncf/kubernetes/example_kubernetes_async.py + :language: python + :start-after: [START howto_operator_k8s_write_xcom_async] + :end-before: [END howto_operator_k8s_write_xcom_async] + +Include error message in email alert +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Any content written to ``/dev/termination-log`` will be retrieved by Kubernetes and +included in the exception message if the task fails. + +.. code-block:: python + + k = KubernetesPodOperator( + task_id="test_error_message", + image="alpine", + cmds=["/bin/sh"], + arguments=["-c", "echo hello world; echo Custom error > /dev/termination-log; exit 1;"], + name="test-error-message", + email="airflow@example.com", + email_on_failure=True, + ) + + +Read more on termination-log `here `__. + +KubernetesPodOperator callbacks +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The :class:`~airflow.providers.cncf.kubernetes.operators.kubernetes_pod.KubernetesPodOperator` supports different +callbacks that can be used to trigger actions during the lifecycle of the pod. In order to use them, you need to +create a subclass of :class:`~airflow.providers.cncf.kubernetes.callbacks.KubernetesPodOperatorCallback` and override +the callbacks methods you want to use. Then you can pass your callback class to the operator using the ``callbacks`` +parameter. + +The following callbacks are supported: + +* on_sync_client_creation: called after creating the sync client +* on_pod_creation: called after creating the pod +* on_pod_starting: called after the pod starts +* on_pod_completion: called when the pod completes +* on_pod_cleanup: called after cleaning/deleting the pod +* on_operator_resuming: when resuming the task from deferred state +* progress_callback: called on each line of containers logs + +Currently, the callbacks methods are not called in the async mode, this support will be added in the future. + +Example: +~~~~~~~~ +.. code-block:: python + + import kubernetes.client as k8s + import kubernetes_asyncio.client as async_k8s + + from airflow.providers.cncf.kubernetes.operators.pod import KubernetesPodOperator + from airflow.providers.cncf.kubernetes.callbacks import KubernetesPodOperatorCallback + + + class MyCallback(KubernetesPodOperatorCallback): + @staticmethod + def on_pod_creation(*, pod: k8s.V1Pod, client: k8s.CoreV1Api, mode: str, **kwargs) -> None: + client.create_namespaced_service( + namespace=pod.metadata.namespace, + body=k8s.V1Service( + metadata=k8s.V1ObjectMeta( + name=pod.metadata.name, + labels=pod.metadata.labels, + owner_references=[ + k8s.V1OwnerReference( + api_version=pod.api_version, + kind=pod.kind, + name=pod.metadata.name, + uid=pod.metadata.uid, + controller=True, + block_owner_deletion=True, + ) + ], + ), + spec=k8s.V1ServiceSpec( + selector=pod.metadata.labels, + ports=[ + k8s.V1ServicePort( + name="http", + port=80, + target_port=80, + ) + ], + ), + ), + ) + + + k = KubernetesPodOperator( + task_id="test_callback", + image="alpine", + cmds=["/bin/sh"], + arguments=["-c", "echo hello world; echo Custom error > /dev/termination-log; exit 1;"], + name="test-callback", + callbacks=MyCallback, + ) + +Reference +^^^^^^^^^ +For further information, look at: + +* `Kubernetes Documentation `__ +* `Pull an Image from a Private Registry `__ + +SparkKubernetesOperator +========================== +The :class:`~airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator` allows +you to create and run spark job on a Kubernetes cluster. It is based on `spark-on-k8s-operator `__ project. + +This operator simplifies the interface and accepts different parameters to configure and run spark application on Kubernetes. +Similar to the KubernetesOperator, we have added the logic to wait for a job after submission, +manage error handling, retrieve logs from the driver pod and the ability to delete a spark job. +It also supports out-of-the-box Kubernetes functionalities such as handling of volumes, config maps, secrets, etc. + + +How does this operator work? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The operator initiates a Spark task by generating a SparkApplication Custom Resource Definition (CRD) within Kubernetes. +This SparkApplication task subsequently generates driver and required executor pods, using the parameters specified by the user. +The operator continuously monitors the task's progress until it either succeeds or fails. +It retrieves logs from the driver pod and displays them in the Airflow UI. + + +Usage examples +^^^^^^^^^^^^^^ +In order to create a SparkKubernetesOperator task, you must provide a basic template that includes Spark configuration and +Kubernetes-related resource configuration. This template, which can be in either YAML or JSON format, serves as a +starting point for the operator. Below is a sample template that you can utilize: + +spark_job_template.yaml + +.. code-block:: yaml + + spark: + apiVersion: sparkoperator.k8s.io/v1beta2 + version: v1beta2 + kind: SparkApplication + apiGroup: sparkoperator.k8s.io + metadata: + namespace: ds + spec: + type: Python + pythonVersion: "3" + mode: cluster + sparkVersion: 3.0.0 + successfulRunHistoryLimit: 1 + restartPolicy: + type: Never + imagePullPolicy: Always + hadoopConf: {} + imagePullSecrets: [] + dynamicAllocation: + enabled: false + initialExecutors: 1 + minExecutors: 1 + maxExecutors: 1 + labels: {} + driver: + serviceAccount: default + container_resources: + gpu: + name: null + quantity: 0 + cpu: + request: null + limit: null + memory: + request: null + limit: null + executor: + instances: 1 + container_resources: + gpu: + name: null + quantity: 0 + cpu: + request: null + limit: null + memory: + request: null + limit: null + kubernetes: + # example: + # env_vars: + # - name: TEST_NAME + # value: TEST_VALUE + env_vars: [] + + # example: + # env_from: + # - name: test + # valueFrom: + # secretKeyRef: + # name: mongo-secret + # key: mongo-password + env_from: [] + + # example: + # node_selector: + # karpenter.sh/provisioner-name: spark + node_selector: {} + + # example: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + # affinity: + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: beta.kubernetes.io/instance-type + # operator: In + # values: + # - r5.xlarge + affinity: + nodeAffinity: {} + podAffinity: {} + podAntiAffinity: {} + + # example: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + # type: list + # tolerations: + # - key: "key1" + # operator: "Equal" + # value: "value1" + # effect: "NoSchedule" + tolerations: [] + + # example: + # config_map_mounts: + # snowflake-default: /mnt/tmp + config_map_mounts: {} + + # example: + # volume_mounts: + # - name: config + # mountPath: /airflow + volume_mounts: [] + + # https://kubernetes.io/docs/concepts/storage/volumes/ + # example: + # volumes: + # - name: config + # persistentVolumeClaim: + # claimName: airflow + volumes: [] + + # read config map into an env variable + # example: + # from_env_config_map: + # - configmap_1 + # - configmap_2 + from_env_config_map: [] + + # load secret into an env variable + # example: + # from_env_secret: + # - secret_1 + # - secret_2 + from_env_secret: [] + + in_cluster: true + conn_id: kubernetes_default + kube_config_file: null + cluster_context: null + +.. important:: + + * The template file consists of two primary categories: ``spark`` and ``kubernetes``. + + * spark: This segment encompasses the task's Spark configuration, mirroring the structure of the Spark API template. + + * kubernetes: This segment encompasses the task's Kubernetes resource configuration, directly corresponding to the Kubernetes API Documentation. Each resource type includes an example within the template. + + * The designated base image to be utilized is ``gcr.io/spark-operator/spark-py:v3.1.1``. + + * Ensure that the Spark code is either embedded within the image, mounted using a persistentVolume, or accessible from an external location such as an S3 bucket. + +Next, create the task using the following: + +.. code-block:: python + + SparkKubernetesOperator( + task_id="spark_task", + image="gcr.io/spark-operator/spark-py:v3.1.1", # OR custom image using that + code_path="local://path/to/spark/code.py", + application_file="spark_job_template.json", # OR spark_job_template.json + dag=dag, + ) + +Note: Alternatively application_file can also be a json file. see below example + +spark_job_template.json + +.. code-block:: json + + { + "spark": { + "apiVersion": "sparkoperator.k8s.io/v1beta2", + "version": "v1beta2", + "kind": "SparkApplication", + "apiGroup": "sparkoperator.k8s.io", + "metadata": { + "namespace": "ds" + }, + "spec": { + "type": "Python", + "pythonVersion": "3", + "mode": "cluster", + "sparkVersion": "3.0.0", + "successfulRunHistoryLimit": 1, + "restartPolicy": { + "type": "Never" + }, + "imagePullPolicy": "Always", + "hadoopConf": {}, + "imagePullSecrets": [], + "dynamicAllocation": { + "enabled": false, + "initialExecutors": 1, + "minExecutors": 1, + "maxExecutors": 1 + }, + "labels": {}, + "driver": { + "serviceAccount": "default", + "container_resources": { + "gpu": { + "name": null, + "quantity": 0 + }, + "cpu": { + "request": null, + "limit": null + }, + "memory": { + "request": null, + "limit": null + } + } + }, + "executor": { + "instances": 1, + "container_resources": { + "gpu": { + "name": null, + "quantity": 0 + }, + "cpu": { + "request": null, + "limit": null + }, + "memory": { + "request": null, + "limit": null + } + } + } + } + }, + "kubernetes": { + "env_vars": [], + "env_from": [], + "node_selector": {}, + "affinity": { + "nodeAffinity": {}, + "podAffinity": {}, + "podAntiAffinity": {} + }, + "tolerations": [], + "config_map_mounts": {}, + "volume_mounts": [ + { + "name": "config", + "mountPath": "/airflow" + } + ], + "volumes": [ + { + "name": "config", + "persistentVolumeClaim": { + "claimName": "hsaljoog-airflow" + } + } + ], + "from_env_config_map": [], + "from_env_secret": [], + "in_cluster": true, + "conn_id": "kubernetes_default", + "kube_config_file": null, + "cluster_context": null + } + } + + + +An alternative method, apart from using YAML or JSON files, is to directly pass the ``template_spec`` field instead of application_file +if you prefer not to employ a file for configuration. + + +Reference +^^^^^^^^^ +For further information, look at: + +* `Kubernetes Documentation `__ +* `Spark-on-k8s-operator Documentation - User guide `__ +* `Spark-on-k8s-operator Documentation - API `__ + + +.. _howto/operator:kubernetesjoboperator: + +KubernetesJobOperator +===================== + +The :class:`~airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator` allows +you to create and run Jobs on a Kubernetes cluster. + +.. note:: + If you use a managed Kubernetes consider using a specialize KJO operator as it simplifies the Kubernetes authorization process : + + - ``GKEStartJobOperator`` operator for `Google Kubernetes Engine `__. + +.. note:: + The :doc:`Kubernetes executor ` is **not** required to use this operator. + +How does this operator work? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The :class:`~airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator` uses the +Kubernetes API to launch a job in a Kubernetes cluster. The operator uses the Kube Python Client to generate a Kubernetes API +request that dynamically launches this Job. +Users can specify a kubeconfig file using the ``config_file`` parameter, otherwise the operator will default +to ``~/.kube/config``. It also allows users to supply a template YAML file using the ``job_template_file`` parameter. + +.. exampleinclude:: /../../tests/system/providers/cncf/kubernetes/example_kubernetes_job.py + :language: python + :dedent: 4 + :start-after: [START howto_operator_k8s_job] + :end-before: [END howto_operator_k8s_job] + +The :class:`~airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator` also supports deferrable mode: + +.. exampleinclude:: /../../tests/system/providers/cncf/kubernetes/example_kubernetes_job.py + :language: python + :dedent: 4 + :start-after: [START howto_operator_k8s_job_deferrable] + :end-before: [END howto_operator_k8s_job_deferrable] + + +Difference between ``KubernetesPodOperator`` and ``KubernetesJobOperator`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The :class:`~airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator` is operator for creating Job. +A Job creates one or more Pods and will continue to retry execution of the Pods until a specified number of them successfully terminate. +As Pods successfully complete, the Job tracks the successful completions. When a specified number of successful completions is reached, the Job is complete. +Users can limit how many times a Job retries execution using configuration parameters like ``activeDeadlineSeconds`` and ``backoffLimit``. +Instead of ``template`` parameter for Pod creating this operator uses :class:`~airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator`. +It means that user can use all parameters from :class:`~airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator` in :class:`~airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator`. + +More information about the Jobs here: `Kubernetes Job Documentation `__ + + +.. _howto/operator:KubernetesDeleteJobOperator: + +KubernetesDeleteJobOperator +=========================== + +The :class:`~airflow.providers.cncf.kubernetes.operators.job.KubernetesDeleteJobOperator` allows +you to delete Jobs on a Kubernetes cluster. + +.. exampleinclude:: /../../tests/system/providers/cncf/kubernetes/example_kubernetes_job.py + :language: python + :dedent: 4 + :start-after: [START howto_operator_delete_k8s_job] + :end-before: [END howto_operator_delete_k8s_job] + + +.. _howto/operator:KubernetesPatchJobOperator: + +KubernetesPatchJobOperator +========================== + +The :class:`~airflow.providers.cncf.kubernetes.operators.job.KubernetesPatchJobOperator` allows +you to update Jobs on a Kubernetes cluster. + +.. exampleinclude:: /../../tests/system/providers/cncf/kubernetes/example_kubernetes_job.py + :language: python + :dedent: 4 + :start-after: [START howto_operator_update_job] + :end-before: [END howto_operator_update_job] diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/security.rst.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/security.rst.txt new file mode 100644 index 00000000000..afa13dac6fc --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sources/security.rst.txt @@ -0,0 +1,18 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +.. include:: ../exts/includes/security.rst diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css new file mode 100644 index 00000000000..eb19f698afc --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css @@ -0,0 +1 @@ +.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative}details.sd-dropdown .sd-summary-title{font-weight:700;padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary{list-style:none;padding:1em}details.sd-dropdown summary .sd-octicon.no-title{vertical-align:middle}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown summary::-webkit-details-marker{display:none}details.sd-dropdown summary:focus{outline:none}details.sd-dropdown .sd-summary-icon{margin-right:.5em}details.sd-dropdown .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary:hover .sd-summary-up svg,details.sd-dropdown summary:hover .sd-summary-down svg{opacity:1;transform:scale(1.1)}details.sd-dropdown .sd-summary-up svg,details.sd-dropdown .sd-summary-down svg{display:block;opacity:.6}details.sd-dropdown .sd-summary-up,details.sd-dropdown .sd-summary-down{pointer-events:none;position:absolute;right:1em;top:1em}details.sd-dropdown[open]>.sd-summary-title .sd-summary-down{visibility:hidden}details.sd-dropdown:not([open])>.sd-summary-title .sd-summary-up{visibility:hidden}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #0071bc;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0060a0;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem} diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sphinx_design_static/design-tabs.js b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sphinx_design_static/design-tabs.js new file mode 100644 index 00000000000..36b38cf0d91 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_sphinx_design_static/design-tabs.js @@ -0,0 +1,27 @@ +var sd_labels_by_text = {}; + +function ready() { + const li = document.getElementsByClassName("sd-tab-label"); + for (const label of li) { + syncId = label.getAttribute("data-sync-id"); + if (syncId) { + label.onclick = onLabelClick; + if (!sd_labels_by_text[syncId]) { + sd_labels_by_text[syncId] = []; + } + sd_labels_by_text[syncId].push(label); + } + } +} + +function onLabelClick() { + // Activate other inputs with the same sync id. + syncId = this.getAttribute("data-sync-id"); + for (label of sd_labels_by_text[syncId]) { + if (label === this) continue; + label.previousElementSibling.checked = true; + } + window.localStorage.setItem("sphinx-design-last-tab", syncId); +} + +document.addEventListener("DOMContentLoaded", ready, false); diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/_gen/css/main-custom.min.css b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/_gen/css/main-custom.min.css new file mode 100644 index 00000000000..46f1de59325 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/_gen/css/main-custom.min.css @@ -0,0 +1 @@ +@charset "UTF-8";@import "https://fonts.googleapis.com/css?family=Rubik:500&display=swap";@import "https://fonts.googleapis.com/css?family=Roboto:400,400i,500,700&display=swap";@import "https://fonts.googleapis.com/css?family=Roboto+Mono:400,700&display=swap";.header__large--cerulean-blue{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#017cee}.header__large--shamrock{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#00ad46}.header__large--bright-sky-blue{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#0cb6ff}.header__large--melon{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#ff7557}.header__large--vermillion{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#e43921}.header__large--aqua{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#11e1ee}.header__large--shamrock-green{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#04d659}.header__large--aqua-blue{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#00c7d4}.header__large--white{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#fff}.header__large--brownish-grey{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#707070}.header__large--very-light-pink{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#cbcbcb}.header__large--slate-grey{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#636365}.header__large--greyish-brown,#header-canvas .text-area--header{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#51504f}.header__medium--cerulean-blue{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#017cee}.header__medium--shamrock{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#00ad46}.header__medium--bright-sky-blue{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#0cb6ff}.header__medium--melon{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#ff7557}.header__medium--vermillion{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#e43921}.header__medium--aqua{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#11e1ee}.header__medium--shamrock-green{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#04d659}.header__medium--aqua-blue{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#00c7d4}.header__medium--white{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#fff}.header__medium--brownish-grey{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#707070}.header__medium--very-light-pink{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#cbcbcb}.header__medium--slate-grey{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#636365}.header__medium--greyish-brown,.page-header{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#51504f}.header__small--cerulean-blue{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#017cee}.header__small--shamrock{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#00ad46}.header__small--bright-sky-blue{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#0cb6ff}.header__small--melon{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#ff7557}.header__small--vermillion{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#e43921}.header__small--aqua{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#11e1ee}.header__small--shamrock-green{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#04d659}.header__small--aqua-blue{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#00c7d4}.header__small--white{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#fff}.header__small--brownish-grey{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#707070}.header__small--very-light-pink{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#cbcbcb}.header__small--slate-grey{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#636365}.header__small--greyish-brown,.blogpost-content__metadata--title,.community--header-join,.community--committers-header{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#51504f}.header__xsmall--cerulean-blue{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#017cee}.header__xsmall--shamrock{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#00ad46}.header__xsmall--bright-sky-blue{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#0cb6ff}.header__xsmall--melon{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#ff7557}.header__xsmall--vermillion{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#e43921}.header__xsmall--aqua{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#11e1ee}.header__xsmall--shamrock-green{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#04d659}.header__xsmall--aqua-blue{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#00c7d4}.header__xsmall--white{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#fff}.header__xsmall--brownish-grey{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#707070}.header__xsmall--very-light-pink{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#cbcbcb}.header__xsmall--slate-grey{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#636365}.header__xsmall--greyish-brown,.feature-item--header,.text-with-icon-item--header{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#51504f}.subtitle__large--cerulean-blue,.box-event__meetup--location{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#017cee}.subtitle__large--shamrock{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#00ad46}.subtitle__large--bright-sky-blue{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#0cb6ff}.subtitle__large--melon{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#ff7557}.subtitle__large--vermillion{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#e43921}.subtitle__large--aqua{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#11e1ee}.subtitle__large--shamrock-green{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#04d659}.subtitle__large--aqua-blue{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#00c7d4}.subtitle__large--white{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#fff}.subtitle__large--brownish-grey,.quote--text,.page-subtitle,.blogpost-content__metadata--description,#header-canvas .text-area--subheader{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#707070}.subtitle__large--very-light-pink{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#cbcbcb}.subtitle__large--slate-grey{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#636365}.subtitle__large--greyish-brown,.box-event__blogpost--header,.markdown-content h1,.markdown-content h2,.markdown-content h3,.markdown-content h4,.markdown-content h5{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#51504f}.subtitle__medium--cerulean-blue,ol.counter-blue li::before{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#017cee}.subtitle__medium--shamrock{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#00ad46}.subtitle__medium--bright-sky-blue{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#0cb6ff}.subtitle__medium--melon{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#ff7557}.subtitle__medium--vermillion{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#e43921}.subtitle__medium--aqua{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#11e1ee}.subtitle__medium--shamrock-green{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#04d659}.subtitle__medium--aqua-blue{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#00c7d4}.subtitle__medium--white{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#fff}.subtitle__medium--brownish-grey,.box-event__integration--name{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#707070}.subtitle__medium--very-light-pink{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#cbcbcb}.subtitle__medium--slate-grey{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#636365}.subtitle__medium--greyish-brown,.roadmap .td-sidebar nav>ul>li>a{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#51504f}.bodytext__medium--cerulean-blue,.box-event__blogpost--author,.box-event__meetup--next-meetup,.tag,.new-entry--link,.blogpost-content__metadata--author{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#017cee}.bodytext__medium--shamrock{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#00ad46}.bodytext__medium--bright-sky-blue{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#0cb6ff}.bodytext__medium--melon{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#ff7557}.bodytext__medium--vermillion{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#e43921}.bodytext__medium--aqua{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#11e1ee}.bodytext__medium--shamrock-green{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#04d659}.bodytext__medium--aqua-blue{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#00c7d4}.bodytext__medium--white,footer .footer-section span{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#fff}.bodytext__medium--brownish-grey,ol.counter-blue li,ul.ticks-blue li,.box-event__blogpost--description,.box-event__blogpost--date,.box-event__case-study--quote,.box-event__meetup--members,.markdown-content p,.markdown-content span,.feature-item--text,.text-with-icon-item--text,.video-list__item .video-list__item--title,.blogpost-content__metadata--date,.install--description,.roadmap .breadcrumb-item a,.roadmap .td-sidebar li>a,.sidebar__version-selector a{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#707070}.bodytext__medium--very-light-pink{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#cbcbcb}.bodytext__medium--slate-grey{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#636365}.bodytext__medium--greyish-brown,.box-event__committer--nick,.quote--author,.list-link,.install__accordions-content--header,.navbar__text-link{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#51504f}.bodytext__mobile--cerulean-blue{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#017cee}.bodytext__mobile--shamrock{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#00ad46}.bodytext__mobile--bright-sky-blue{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#0cb6ff}.bodytext__mobile--melon{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#ff7557}.bodytext__mobile--vermillion{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#e43921}.bodytext__mobile--aqua{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#11e1ee}.bodytext__mobile--shamrock-green{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#04d659}.bodytext__mobile--aqua-blue{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#00c7d4}.bodytext__mobile--white{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#fff}.bodytext__mobile--brownish-grey{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#707070}.bodytext__mobile--very-light-pink{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#cbcbcb}.bodytext__mobile--slate-grey{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#636365}.bodytext__mobile--greyish-brown{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#51504f}.bodytext__small--cerulean-blue{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#017cee}.bodytext__small--shamrock{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#00ad46}.bodytext__small--bright-sky-blue{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#0cb6ff}.bodytext__small--melon{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#ff7557}.bodytext__small--vermillion{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#e43921}.bodytext__small--aqua{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#11e1ee}.bodytext__small--shamrock-green{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#04d659}.bodytext__small--aqua-blue{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#00c7d4}.bodytext__small--white{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#fff}.bodytext__small--brownish-grey{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#707070}.bodytext__small--very-light-pink{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#cbcbcb}.bodytext__small--slate-grey{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#636365}.bodytext__small--greyish-brown{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#51504f}.bodytext__xsmall--cerulean-blue{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#017cee}.bodytext__xsmall--shamrock{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#00ad46}.bodytext__xsmall--bright-sky-blue{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#0cb6ff}.bodytext__xsmall--melon{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#ff7557}.bodytext__xsmall--vermillion{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#e43921}.bodytext__xsmall--aqua{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#11e1ee}.bodytext__xsmall--shamrock-green{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#04d659}.bodytext__xsmall--aqua-blue{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#00c7d4}.bodytext__xsmall--white{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#fff}.bodytext__xsmall--brownish-grey{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#707070}.bodytext__xsmall--very-light-pink{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#cbcbcb}.bodytext__xsmall--slate-grey{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#636365}.bodytext__xsmall--greyish-brown{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#51504f}.monotext--cerulean-blue{font-family:roboto mono,monospace;color:#017cee;font-size:14px;line-height:1.71}.monotext--shamrock{font-family:roboto mono,monospace;color:#00ad46;font-size:14px;line-height:1.71}.monotext--bright-sky-blue{font-family:roboto mono,monospace;color:#0cb6ff;font-size:14px;line-height:1.71}.monotext--melon{font-family:roboto mono,monospace;color:#ff7557;font-size:14px;line-height:1.71}.monotext--vermillion{font-family:roboto mono,monospace;color:#e43921;font-size:14px;line-height:1.71}.monotext--aqua{font-family:roboto mono,monospace;color:#11e1ee;font-size:14px;line-height:1.71}.monotext--shamrock-green{font-family:roboto mono,monospace;color:#04d659;font-size:14px;line-height:1.71}.monotext--aqua-blue{font-family:roboto mono,monospace;color:#00c7d4;font-size:14px;line-height:1.71}.monotext--white{font-family:roboto mono,monospace;color:#fff;font-size:14px;line-height:1.71}.monotext--brownish-grey,.markdown-content pre span,pre span{font-family:roboto mono,monospace;color:#707070;font-size:14px;line-height:1.71}.monotext--very-light-pink{font-family:roboto mono,monospace;color:#cbcbcb;font-size:14px;line-height:1.71}.monotext--slate-grey{font-family:roboto mono,monospace;color:#636365;font-size:14px;line-height:1.71}.monotext--greyish-brown{font-family:roboto mono,monospace;color:#51504f;font-size:14px;line-height:1.71}.font-weight-normal{font-weight:400!important}.font-weight-500{font-weight:500!important}.font-weight-bold{font-weight:700!important}details.accordion{padding:40px 30px;border-bottom:solid 1px #cbcbcb;-webkit-transition:ease 1s;-o-transition:ease 1s;transition:ease 1s}details.accordion:first-of-type{border-top:solid 1px #cbcbcb}details.accordion summary{position:relative;display:block;outline:none}details.accordion summary::-webkit-details-marker{display:none}details.accordion .accordion__summary-content{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;max-width:750px;margin-right:40px}details.accordion .accordion__summary-content--icon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;width:60px;margin-right:42px}details.accordion .accordion__summary-content--header{margin-bottom:20px}details.accordion .accordion__arrow{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;position:absolute;width:36px;height:36px;top:0;right:0;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;border:solid 1px #017cee;border-radius:50%}details.accordion .accordion__arrow svg{-webkit-transition:ease-out .2s;-o-transition:ease-out .2s;transition:ease-out .2s}details.accordion[open] .accordion__arrow svg{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}details.accordion .accordion__content{margin-top:30px;margin-right:36px}details.accordion .accordion__content.indented{margin-left:102px}@media(max-width:1280px){details.accordion{padding:30px 0}details.accordion .accordion__summary-content--icon{-webkit-box-align:unset;-webkit-align-items:unset;-ms-flex-align:unset;align-items:unset;margin-right:20px;margin-top:28px}details.accordion .accordion__arrow{width:28px;height:28px;top:5px}details.accordion .accordion__content.indented{margin-left:80px}details.accordion .accordion__content ol.counter-blue{margin-left:-38px!important}}button{cursor:pointer;border:1px solid;border-radius:5px;padding:9px 29px;-webkit-transition:all ease-out .2s;-o-transition:all ease-out .2s;transition:all ease-out .2s}button:disabled{cursor:not-allowed}button.btn-filled{border-color:#017cee;background-color:#017cee}button.btn-filled:hover{border-color:#0cb6ff;background-color:#0cb6ff}button.btn-with-icon{padding:14px 20px}button.btn-with-icon svg{height:30px;width:auto;padding-right:15px}button.btn-with-icon span{display:inline-block;line-height:30px;vertical-align:middle}button.btn-hollow{background-color:#fff}button.btn-hollow.btn-blue{color:#017cee;border-color:#017cee}button.btn-hollow.btn-blue:disabled{color:#cbcbcb;border-color:#cbcbcb}button.btn-hollow.btn-blue:hover:enabled{color:#fff;background-color:#017cee}button.btn-hollow.btn-brown{border-color:#cbcbcb}button.btn-hollow.btn-brown:hover{background-color:#51504f;border-color:#51504f}button.btn-hollow.btn-brown:hover span{color:#fff}button.btn-hollow.btn-brown:hover svg path{fill:#fff}button.with-box-shadow{-webkit-box-shadow:0 2px 6px 0 rgba(0,0,0,.12);box-shadow:0 2px 6px 0 rgba(0,0,0,.12)}@media(max-width:1280px){button{padding:4px 17px}}ol.counter-blue,ul.ticks-blue{list-style:none;margin-bottom:0}ol.counter-blue li,ul.ticks-blue li{position:relative;padding-left:10px}ol.counter-blue li::before,ul.ticks-blue li::before{position:absolute;border:solid 1px #017cee;border-radius:50%}ol.counter-blue{counter-reset:custom-counter;padding-left:-webkit-calc(26px + 2px);padding-left:calc(26px + 2px)}ol.counter-blue li{counter-increment:custom-counter;margin-bottom:25px}ol.counter-blue li::before{content:counter(custom-counter);-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;top:-2px;left:-webkit-calc(-1 * 26px);left:calc(-1 * 26px);width:26px;height:26px;text-align:center;line-height:26px}ul.ticks-blue{padding-left:-webkit-calc(24px + 2px);padding-left:calc(24px + 2px)}ul.ticks-blue li{margin-bottom:22px}ul.ticks-blue li::before{content:"";left:-webkit-calc(-1 * 24px);left:calc(-1 * 24px);width:24px;height:24px;background-position:50%;background-repeat:no-repeat;background-image:url(/images/tick.svg)}.list-items{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin:-20px;-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch}@media(max-width:1280px){.list-items{margin:auto;max-width:580px}}@media(max-width:640px){.list-items{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}}.list-item{width:25%;padding:20px}@media(min-width:1920px){.list-item{width:20%}}@media(max-width:1280px){.list-item{padding:10px;width:50%}}@media(max-width:640px){.list-item{width:100%}}.list-item--wide{width:50%}@media(max-width:1280px){.list-item--wide{width:100%}}.card{border:solid 1px #cbcbcb;border-radius:5px;padding:30px 10px;height:100%}.box-event{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.box-event__blogpost{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;padding:0 20px}.box-event__blogpost--metadata{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;margin-bottom:20px}.box-event__blogpost--header{margin-bottom:4px}.box-event__blogpost--author{font-weight:500}.box-event__blogpost--description{margin-bottom:20px}.box-event__case-study{padding:18px 18px 0;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.box-event__case-study--logo{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;height:60px;width:100%;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.box-event__case-study--logo svg,.box-event__case-study--logo img{max-height:100%;max-width:100%}.box-event__case-study--quote{font-style:italic;margin:30px 0 20px;text-align:center}.box-event__case-study--quote::before{content:"“"}.box-event__case-study--quote::after{content:"”"}.box-event__committer--nick{font-weight:500;margin-top:12px}.box-event__committer--social-media-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.box-event__committer--social-media-icon{margin:0 6px}.box-event__meetup--location{margin-bottom:10px;text-align:center}.box-event__meetup--members{margin-bottom:30px}.box-event__meetup--members span{vertical-align:middle}.box-event__meetup--next-meetup{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;min-height:52px;margin-bottom:20px;text-align:center}.box-event__integration{height:208px;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.box-event__integration--logo{margin:auto 0;-webkit-filter:grayscale(1);filter:grayscale(1);opacity:.6;max-width:100%;max-height:100%}.box-event__integration--name{font-weight:700;text-align:center}.box-event__integration:hover .box-event__integration--logo{-webkit-filter:none;filter:none;opacity:1}.box-event.hoverable-icon svg,.box-event.hoverable-icon img{-webkit-filter:grayscale(1);filter:grayscale(1);opacity:.6;-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s}.box-event.hoverable-icon:hover svg,.box-event.hoverable-icon:hover img{-webkit-filter:none;filter:none;opacity:1}@media(max-width:640px){.box-event__blogpost--metadata{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.box-event__blogpost--date{margin-top:17px}}.avatar{border-radius:50%;width:80px;height:80px}.quote{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;border-bottom:solid 1px #cbcbcb;padding:0 78px 60px}.quote--text{text-align:center;font-weight:400}.quote--text::before{content:"“"}.quote--text::after{content:"”"}.quote--author{text-align:center;font-weight:500;margin-bottom:32px}.quote--logo{max-height:140px;margin:0 auto}@media(max-width:640px){.quote{padding:0 0 40px}}.pager{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;margin-top:60px}.case-study-page{max-width:790px!important;margin:60px auto 0}@media(max-width:640px){.case-study-page{margin-top:40px}}.markdown-content h1,.markdown-content h2,.markdown-content h3,.markdown-content h4,.markdown-content h5{margin-top:40px;margin-bottom:20px}.markdown-content p,.markdown-content span{margin-bottom:30px;margin-top:20px}.markdown-content img{width:100%}.markdown-content table{border-collapse:collapse;width:100%}.markdown-content th{background:#ccc}.markdown-content th,.markdown-content td{border:1px solid #ccc;padding:8px}.markdown-content tr:nth-child(even){background:#efefef}.markdown-content tr:hover{background:#d1d1d1}.markdown-content li{color:#707070}.base-layout{padding:123px 0 40px}.base-layout--button{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;position:-webkit-sticky;position:sticky;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;margin-left:auto;margin-right:40px;bottom:40px;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;z-index:1}@media(max-width:1280px){.base-layout{padding:76px 0 60px}.base-layout--button{display:none}}.page-header{text-align:center;margin-bottom:16px}@media(max-width:1280px){.page-header{font-size:36px!important;line-height:1.22!important}}.page-subtitle{text-align:center;font-weight:400!important;margin-bottom:80px}@media(max-width:1280px){.page-subtitle{font-family:roboto,sans-serif!important;font-size:16px!important;line-height:1.63!important;margin-bottom:30px}}.container{margin-top:44px;max-width:1200px}@media(min-width:1920px){.container{max-width:1510px}}@media(max-width:1280px){.container>*{max-width:630px;margin-left:auto;margin-right:auto}.container .no-width-restriction{max-width:none}}@media(max-width:640px){.container>*{max-width:306px}}.container-fluid{padding-left:20px;padding-right:20px}.show-more-button{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;margin:60px auto 0}@media(max-width:1280px){.show-more-button{margin-top:30px}}@media(max-width:1280px){.desktop-only{display:none}}@media(min-width:calc(1280px + 1px)){.no-desktop{display:none}}@media(min-width:calc(640px + 1px)){.mobile-only{display:none}}.features-list{margin:76px auto 100px;max-width:720px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}@media(min-width:1920px){.features-list{max-width:unset;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;margin-top:0}}@media(max-width:640px){.features-list{margin-top:0}}.feature-item{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin:44px auto 0}.feature-item--icon-box{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;max-width:150px;width:100%;height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;margin-top:18px}.feature-item--text-box{margin-left:60px}@media(min-width:1920px),(max-width:1280px){.feature-item{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.feature-item--icon-box{margin-top:0;margin-bottom:20px;max-width:unset}.feature-item--text-box{margin-left:0;text-align:center}}@media(min-width:1920px){.feature-item{margin-top:60px;max-width:392px;margin-left:40px;margin-right:40px}}@media(max-width:1280px){.feature-item{margin-top:40px;max-width:260px}.feature-item svg{height:60px;width:auto}.feature-item--header{font-family:roboto,sans-serif!important;font-size:24px!important;line-height:1.5!important}.feature-item--text{font-size:14px!important;line-height:1.57!important}}.text-with-icon-list{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;max-width:940px;margin:0 auto 100px;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.text-with-icon-item{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-width:410px;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;margin-top:54px}.text-with-icon-item svg{height:100px}.text-with-icon-item--header{text-align:center;margin-top:23px}.text-with-icon-item--text{text-align:center}@media(min-width:1920px){.text-with-icon-list{max-width:unset}.text-with-icon-item{max-width:305px}}@media(max-width:1280px){.text-with-icon-item{margin-top:30px;max-width:276px}.text-with-icon-item svg{width:70px;height:70px}.text-with-icon-item--header{font-family:roboto,sans-serif;font-size:24px;line-height:1.5;margin-top:16px}.text-with-icon-item--text{font-size:14px;line-height:1.57}}@media(max-width:640px){.text-with-icon-list{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}}.video-section{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;border:solid 1px #cbcbcb;padding:40px}@media(max-width:1280px){.video-section{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-width:560px;margin:0 auto;padding:20px}}.video-wrapper{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.video-wrapper .video-container{display:none}.video-wrapper .video-container:last-child{display:block}.video-wrapper .anchor{position:fixed}.video-wrapper .anchor:target+.video-container{display:block}.video-wrapper .anchor:target+.video-container~.video-container{display:none}.video-list-wrapper{overflow-y:auto;max-height:403px;max-width:370px;width:100%;margin-left:40px}@media(max-width:1280px){.video-list-wrapper{max-width:unset;margin-left:0}}.video-list-wrapper::-webkit-scrollbar{-webkit-appearance:none}.video-list-wrapper::-webkit-scrollbar-thumb{border-radius:8px;border:2px solid #fff;background-color:rgba(0,0,0,.5)}.video-list-wrapper::-webkit-scrollbar:vertical{width:9px}.video-list{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end}.video-list__item{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;border-bottom:solid 1px #cbcbcb;padding:16px 0}.video-list__item .video-list__item--title{margin-left:9px;vertical-align:middle}.video-list__item--icon-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.video-list__item:hover .video-list__item--title,.video-list__item.active .video-list__item--title{font-weight:500}.video-list__item:hover svg path,.video-list__item.active svg path{fill:#707070;stroke:none}.tag{display:block;background-color:rgba(1,124,238,.25);padding:1px 15px;border-radius:5px;-webkit-transition:.2s;-o-transition:.2s;transition:.2s;margin:7px}.tag.active,.tag:hover{background-color:#017cee;color:#fff}.tags-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;margin:-7px}@media(max-width:640px){.tags-container{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;margin-bottom:7px}}.all-tags-container{margin:30px 0}.blog__list-items-wrapper{max-width:1200px;margin:30px auto 0}@media(max-width:1280px){.blog__list-items-wrapper{max-width:580px}}.new-entry{margin-bottom:20px}.new-entry--link{font-weight:500}@media(max-width:1280px){.new-entry{margin-bottom:10px;padding-left:10px}}.blogpost-content{max-width:790px;margin:0 auto}.blogpost-content--header-wrapper{border-bottom:solid 1px #cbcbcb}.blogpost-content__metadata--container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;margin-bottom:30px}.blogpost-content__metadata--title{margin-bottom:20px}.blogpost-content__metadata--author{font-weight:500;margin-bottom:30px;margin-right:17px}.blogpost-content__metadata--social-media-icon{margin-right:7px}.blogpost-content__metadata--description{font-weight:400;margin-bottom:30px}.blogpost-content__metadata--date{margin-top:17px}@media(max-width:640px){.blogpost-content__metadata--container{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;margin-bottom:19px}.blogpost-content__metadata--title{font-family:roboto,sans-serif!important;font-size:24px!important;line-height:1.5!important;max-width:272px;margin-bottom:13px}.blogpost-content__metadata--author{margin-bottom:20px}.blogpost-content__metadata--description{font-family:roboto,sans-serif!important;font-weight:400!important;font-size:16px!important;line-height:1.63!important;margin-bottom:20px}}.blog-pager{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;max-width:1200px;margin:60px auto 0}.blog-pager .pager{margin-top:40px;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.home-page-layout.base-layout{padding-top:70px}@media(max-width:640px){.home-page-layout.base-layout{padding-top:16px}}.principles-header{margin-top:20px;margin-bottom:4px}.integrations-header{margin-bottom:60px}@media(max-width:640px){.integrations-header{margin-bottom:30px}}#integrations .list-items{margin-top:40px}@media(max-width:640px){#integrations .list-items{margin-top:20px}}.video-section-container{margin:80px auto;max-width:1200px}@media(max-width:640px){.video-section-container{margin:60px 0}}.host-header{margin-bottom:6px}.meetups{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.meetups>.list-items{margin-top:40px;margin-bottom:40px;width:100%}@media(max-width:1280px){.meetups>.list-items{margin-top:30px;margin-bottom:30px}}@media(max-width:640px){.meetups>.list-items{margin-bottom:10px}}.meetups-page.page-subtitle{margin-bottom:0}.list-link{text-decoration:underline}.community--header-container{max-width:936px;margin:0 auto}.community--header-join{text-align:center}.community--accordion-container{margin:60px 18px}.community--committers-header{text-align:center;margin-top:70px;margin-bottom:40px}.community--committers-header.large-margin{margin-top:100px;margin-bottom:40px}@media(min-width:1920px){.community .list-items{max-width:1220px;margin-right:auto;margin-left:auto}.community .list-item{width:25%}}@media(max-width:1280px){.community--header-container{max-width:580px}.community--header-join{font-family:roboto,sans-serif!important;font-size:24px!important;line-height:1.5!important}.community--accordion-container{margin:40px 0}.community--committers-header{font-size:36px!important;line-height:1.22!important;margin-top:60px}.community--committers-header.large-margin{margin-top:60px;margin-bottom:40px}.community--button-container{margin-top:20px}}.install .page-subtitle{margin-bottom:45px}.install--headers-wrapper{max-width:936px;margin:0 auto}.install--description{text-align:center;margin:45px 0 60px}.install--description a{color:#017cee;text-decoration:underline}.install__accordions--wrapper{max-width:900px;margin:60px auto}.install__accordions-content--header{font-weight:500}.install__accordions-content--list-wrapper{margin-bottom:40px}.install__accordions-content--methods-wrapper{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-bottom:20px}.install__accordions-content--method-box{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:270px;height:160px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;border:solid 1px #cbcbcb;border-radius:5px;margin-right:40px}@media(max-width:1280px){.install .page-subtitle{margin-bottom:30px}.install--headers-wrapper{max-width:580px}.install--description{margin-top:30px;margin-bottom:30px}.install__accordions--wrapper{max-width:580px;margin-top:40px;margin-bottom:0}}@media(max-width:640px){.install__accordions-content--methods-wrapper{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;margin-bottom:0;margin-right:-36px}.install__accordions-content--method-box{margin-right:0;margin-bottom:20px}}footer{min-height:unset}footer .footer-section{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}footer .footer-section__media-section{padding:60px 60px 30px;background-color:#51504f}footer .footer-section__media-section--link{margin-right:30px}footer .footer-section__media-section--button-with-text{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}footer .footer-section__media-section--text{margin-right:20px}footer .footer-section__policies-section{padding:30px 60px;background-color:#636365;font-size:12px;-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}footer .footer-section__policies-section span{font-size:12px}footer .footer-section__policies-section--policies{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}footer .footer-section__policies-section--policy-item::before{content:"\00a0\00a0"}footer .footer-section__policies-section--policy-item::after{content:"\00a0\00a0|";color:#fff}footer .footer-section__policies-section--policy-item:last-of-type::after{content:"\00a0\00a0|\00a0\00a0"}footer .footer-section__policies-section--disclaimer{display:block;max-width:600px;color:#cbcbcb!important;margin-top:16px}@media(min-width:1920px){footer .footer-section__policies-section--disclaimer{max-width:800px}}footer .dropdown-toggle::after{color:#fff;vertical-align:middle}@media(max-width:1280px){footer .footer-section{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start}footer .footer-section span{font-size:14px!important;line-height:1.57!important}footer .footer-section__media-section{padding:30px 40px}footer .footer-section__media-section svg{height:31px;width:auto}footer .footer-section__media-section--link{margin-right:20px}footer .footer-section__media-section--button-with-text{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;margin-bottom:47px}footer .footer-section__media-section--text{margin-right:0;margin-bottom:16px}footer .footer-section__policies-section{padding:30px 40px}footer .footer-section__policies-section--policies{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}footer .footer-section__policies-section--policy-item::before,footer .footer-section__policies-section--policy-item::after,footer .footer-section__policies-section--policy-item:last-of-type::before,footer .footer-section__policies-section--policy-item:last-of-type::after{content:""}footer .footer-section__policies-section--language-toggle{margin:17px 0 35px}}.navbar{position:fixed;top:0;width:100%;background-color:#fff;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start;border-bottom:solid 1px #cbcbcb;z-index:32;padding:30px 60px}.navbar__menu-container{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1}.navbar__menu-content{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding-top:16px;padding-left:88px}.navbar__links-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.navbar__text-link{margin-right:30px;position:relative;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.navbar__text-link::before,.navbar__text-link::after{content:"";position:absolute;top:100%;width:0;right:0;height:2px;background-color:#017cee;-webkit-transition:.2s ease-out;-o-transition:.2s ease-out;transition:.2s ease-out}.navbar__text-link:hover,.navbar__text-link.active{color:#51504f}.navbar__text-link:hover::before,.navbar__text-link:hover::after,.navbar__text-link.active::before,.navbar__text-link.active::after{width:100%;left:0}.navbar--box-shadow{-webkit-box-shadow:0 2px 6px 0 rgba(0,0,0,.12);box-shadow:0 2px 6px 0 rgba(0,0,0,.12)}@media(max-width:1280px){.navbar{padding:20px}.navbar__icon-container svg{width:93px;height:auto}.navbar__menu-content{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;padding-left:0;padding-top:0}.navbar__drawer-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end}.navbar__toggle-button{border:none;background:0 0;padding:0;position:relative;width:26px;height:20px}.navbar__toggle-button--icon{position:absolute;top:0;bottom:0;left:0;right:0;visibility:hidden;opacity:0;-webkit-transition:.2s ease-out;-o-transition:.2s ease-out;transition:.2s ease-out}.navbar__toggle-button--icon.visible{visibility:visible;opacity:1}.navbar__drawer{position:fixed;top:77px;left:0;width:100%;height:-webkit-calc(100% - 77px);height:calc(100% - 77px);background-color:#fff;-webkit-transform:translateX(100%);-ms-transform:translateX(100%);-o-transform:translateX(100%);transform:translateX(100%);-webkit-transition:.2s ease-out;-o-transition:.2s ease-out;transition:.2s ease-out;padding:40px 40px 30px}.navbar__drawer--open{-webkit-transform:translateX(0);-ms-transform:translateX(0);-o-transform:translateX(0);transform:translateX(0)}.navbar__links-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.navbar__text-link{margin-right:0;margin-bottom:10px}.navbar__text-link:last-child{margin-bottom:20px}}#header{position:relative;margin:123px -20px 0;min-height:-webkit-calc(100vh - 123px);min-height:calc(100vh - 123px)}#header-canvas{padding:0;margin:0;position:absolute;width:100%;height:100%;top:0;left:0;right:0;bottom:0}#header-canvas .text-area{max-width:706px;width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);-o-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}#header-canvas .text-area--header{text-align:center;margin-bottom:20px}#header-canvas .text-area--subheader{font-weight:400!important;text-align:center;margin-bottom:20px}#header-canvas canvas{position:absolute;top:0;left:0;width:100%;height:100%;z-index:-1}@media(min-width:1920px){#header-canvas .text-area--header{font-size:90px}}@media(max-width:1280px){#header{margin:77px -20px 0;min-height:-webkit-calc(100vh - 77px);min-height:calc(100vh - 77px)}#header-canvas .text-area{max-width:450px}#header-canvas .text-area--header{margin-bottom:14px}#header-canvas .text-area--subheader{margin-bottom:26px}}@media(max-width:640px){#header-canvas .text-area{max-width:290px}#header-canvas .text-area--header{font-size:48px!important;line-height:1.25!important}#header-canvas .text-area--subheader{font-size:16px!important;line-height:1.63!important}}.roadmap{margin-top:40px}.roadmap main{padding-left:40px}.roadmap .breadcrumb{padding-bottom:0;margin-bottom:30px}.roadmap .breadcrumb-item+.breadcrumb-item{padding-left:4px}.roadmap .breadcrumb-item+.breadcrumb-item::before{color:#707070;padding-right:0}.roadmap .td-sidebar{position:-webkit-sticky;position:sticky;top:163px;height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;max-height:-webkit-calc(100vh - 163px);max-height:calc(100vh - 163px);max-width:270px;min-width:270px;width:100%;overflow-y:auto;padding-top:12px;padding-left:15px;padding-bottom:30px;margin-left:40px;background-color:#f9f9f9;border:none}.roadmap .td-sidebar::-webkit-scrollbar{-webkit-appearance:none}.roadmap .td-sidebar::-webkit-scrollbar-thumb{border-radius:8px;border:2px solid #fff;background-color:rgba(0,0,0,.5)}.roadmap .td-sidebar::-webkit-scrollbar:vertical{width:9px}.roadmap .td-sidebar__inner{position:static;height:unset}.roadmap .td-sidebar li>a{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.roadmap .td-sidebar li>a.active{color:#017cee}.roadmap .td-sidebar .searchb-box{margin-bottom:26px}.roadmap .td-sidebar .searchb-box .search-form{width:100%}.roadmap .td-sidebar .toctree li{list-style:none;font-family:roboto,sans-serif;font-size:16px;font-weight:400;font-stretch:normal;font-style:normal;line-height:1.63;letter-spacing:normal;color:#707070}.roadmap .td-sidebar .toctree ul{padding-left:15px;display:none}.roadmap .td-sidebar .toctree>ul,.roadmap .td-sidebar .toctree li.current>ul{display:block}.roadmap .td-sidebar .toctree .caption{font-family:roboto,sans-serif;font-size:18px;font-weight:700;font-stretch:normal;font-style:normal;line-height:1.33;letter-spacing:normal;color:#51504f;padding-bottom:13px;text-transform:uppercase;margin-bottom:0}.roadmap .td-sidebar .toctree .current{color:#017cee;font-weight:500}.roadmap .td-sidebar .toctree .current>a:not([href="#"]){color:#017cee}.roadmap .td-sidebar .toctree a .toctree-expand{display:inline-block;position:relative;height:1em}.roadmap .td-sidebar .toctree a .toctree-expand::before{position:absolute;top:6px;left:-12px;content:'►';font-size:7px}.roadmap .td-sidebar .toctree .current>a>.toctree-expand:before{content:'▼'}.roadmap .td-sidebar-nav__section{padding-right:0}.roadmap .td-sidebar-nav>.td-sidebar-nav__section .td-sidebar-nav__section{list-style:none;position:relative;margin-left:10px}.roadmap .td-sidebar-nav>.td-sidebar-nav__section .td-sidebar-nav__section::before{content:'►';position:absolute;top:6px;left:-12px;font-size:8px;color:#51504f}.roadmap .td-sidebar-nav>.td-sidebar-nav__section .td-sidebar-nav__section>ul{display:none}.roadmap .td-sidebar-nav>.td-sidebar-nav__section .td-sidebar-nav__section.current-section::before{content:'▼'}.roadmap .td-sidebar-nav>.td-sidebar-nav__section .td-sidebar-nav__section.current-section>ul{display:block}.roadmap .wy-nav-side-toc{position:-webkit-sticky;position:sticky;top:163px;overflow-x:hidden;overflow-y:auto;width:280px;height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;max-height:-webkit-calc(100vh - 163px);max-height:calc(100vh - 163px);font-size:14px;line-height:1.43}.roadmap .wy-nav-side-toc::-webkit-scrollbar{-webkit-appearance:none}.roadmap .wy-nav-side-toc::-webkit-scrollbar-thumb{border-radius:8px;border:2px solid #fff;background-color:rgba(0,0,0,.5)}.roadmap .wy-nav-side-toc::-webkit-scrollbar:vertical{width:9px}.roadmap .wy-nav-side-toc ul,.roadmap .wy-nav-side-toc ol{padding:0;list-style:none none}.roadmap .wy-nav-side-toc li{list-style:none}.roadmap .wy-nav-side-toc .wy-menu-vertical>ul,.roadmap .wy-nav-side-toc .wy-menu-vertical li.current>ul{padding-left:1px}.roadmap .wy-nav-side-toc .wy-menu-vertical a{display:inline-block;padding:.4045em 0;color:#707070}.roadmap .wy-nav-side-toc .wy-menu-vertical li a{border-left:solid 2px #cbcbcb;padding-left:-webkit-calc(1.25em + 1px);padding-left:calc(1.25em + 1px)}.roadmap .wy-nav-side-toc .wy-menu-vertical li.current{margin-left:-1px}.roadmap .wy-nav-side-toc .wy-menu-vertical li.current>a{border-left:solid 4px #017cee;color:#017cee}.roadmap .wy-nav-side-toc .wy-menu-vertical li li>a{padding-left:2.427em}.roadmap .wy-nav-side-toc .wy-menu-vertical li li li>a{padding-left:4.045em}.roadmap .wy-nav-side-toc .wy-menu-vertical li li li li>a{padding-left:5.663em}@media(max-width:1280px){.roadmap main{padding-left:0}.roadmap .td-sidebar{position:static;background-color:transparent;padding:0;margin:0;max-width:unset;height:530px}}.search-form{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:344px;padding:8px 20px;border:solid 1px #cbcbcb;border-radius:5px;margin:60px auto 0}.search-form__input{font-family:roboto,sans-serif;font-size:16px;color:#707070;line-height:1.63;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;padding-right:10px;border:none;background:0 0;outline:none;float:left}.search-form__button{border:none;background-color:transparent;padding:0}@media(max-width:1280px){.search-form{width:270px;padding:3px 20px;margin-top:30px}}.rating-container{margin-top:40px}.rating{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.rate-star{cursor:pointer;margin-right:13px}.rate-star svg path{fill:none;stroke:#51504f}.rate-star:hover svg path,.rate-star:hover~.rate-star svg path{fill:#017cee;stroke:none}.rst-content{color:#707070}.rst-content h1{margin-top:0;margin-bottom:30px;font-weight:500;font-family:rubik,sans-serif;color:#51504f;font-size:225%}.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6,.rst-content p{font-family:roboto,sans-serif;color:#707070}.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-top:40px;margin-bottom:20px;font-weight:500}.rst-content p{line-height:1.63;margin:0 0 30px;font-size:16px;overflow-wrap:break-word}.rst-content h2{font-size:150%}.rst-content h3{font-size:125%}.rst-content h4{font-size:115%}.rst-content h5{font-size:110%}.rst-content h6{font-size:100%}.rst-content code{max-width:100%;color:#51504f;padding:0 5px;font-family:roboto mono,monospace;overflow-x:auto}.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .admonition-todo,.rst-content .admonition{padding:9px 10px;line-height:24px;margin-bottom:24px;background:#e7f2fa}@media(max-width:768px){.rst-content .admonition p:not(.admonition-title){font-size:12px;line-height:1.83}}.rst-content .admonition-title:before{content:"!";background-color:#fff;border-radius:50%;padding:0 4px;margin-right:5px}.rst-content .admonition-title{color:#fff;font-weight:500;font-size:10px;line-height:2.1;display:block;background:#68d1ff;margin:-10px;padding:0 12px;margin-bottom:9px}.rst-content .danger,.rst-content .error{background:#fdece9}.rst-content .danger::before,.rst-content .error::before{color:#fdece9}.rst-content .danger .admonition-title,.rst-content .error .admonition-title{background:#ee8170}.rst-content .danger .admonition-title::before,.rst-content .error .admonition-title::before{color:#ee8170}.rst-content .attention,.rst-content .caution{background:#fff8f6}.rst-content .warning{background:#f8f8f8}.rst-content .attention .admonition-title,.rst-content .caution .admonition-title{background:#ffa996}.rst-content .attention .admonition-title::before,.rst-content .caution .admonition-title::before{color:#ffa996}.rst-content .warning .admonition-title{background:#a6a6a6}.rst-content .warning .admonition-title::before{color:#a6a6a6}.rst-content .note,.rst-content .seealso{background:#f3fbff}.rst-content .note .admonition-title,.rst-content .seealso .admonition-title{background:#68d2fe}.rst-content .note .admonition-title::before,.rst-content .seealso .admonition-title::before{color:#68d2fe}.rst-content .hint{background:#f2fef6}.rst-content .important{background:#e6f9fc}.rst-content .tip{background:#e5f7ec}.rst-content .hint .admonition-title{background:#63e598}.rst-content .hint .admonition-title::before{color:#63e598}.rst-content .important .admonition-title{background:#5bdae3}.rst-content .important .admonition-title::before{color:#5bdae3}.rst-content .tip .admonition-title{background:#5bcb88}.rst-content .tip .admonition-title::before{color:#5bcb88}.rst-content .note p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.rst-content .seealso p:last-child,.rst-content .admonition p:last-child{margin-bottom:0}.rst-content img{max-width:100%;height:auto}.rst-content div.figure{margin-bottom:24px}.rst-content div.figure p.caption{font-style:italic}.rst-content div.figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center{text-align:center}.rst-content .section>img,.rst-content .section>a>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre{background-color:#f2f8fe}.rst-content pre.literal-block,.rst-content .linenodiv pre{font-family:roboto mono,monospace;font-size:12px;line-height:1.4}@media print{.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol p,.rst-content .section ul p{margin-bottom:12px}.rst-content .section ol li p:last-child,.rst-content .section ul li p:last-child{margin-bottom:0}.rst-content .section ol p:last-child,.rst-content .section ul p:last-child{margin-bottom:24px}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:inherit}.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content .toctree-wrapper p.caption .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink,.rst-content .code-block-caption .headerlink{visibility:hidden;font-size:0}.rst-content h1 .headerlink:after,.rst-content h2 .headerlink:after,.rst-content .toctree-wrapper p.caption .headerlink:after,.rst-content h3 .headerlink:after,.rst-content h4 .headerlink:after,.rst-content h5 .headerlink:after,.rst-content h6 .headerlink:after,.rst-content dl dt .headerlink:after,.rst-content p.caption .headerlink:after,.rst-content table>caption .headerlink:after,.rst-content .code-block-caption .headerlink:after{content:url(/images/anchor.svg);vertical-align:bottom;padding-left:8px}.rst-content h1:hover .headerlink:after,.rst-content h2:hover .headerlink:after,.rst-content .toctree-wrapper p.caption:hover .headerlink:after,.rst-content h3:hover .headerlink:after,.rst-content h4:hover .headerlink:after,.rst-content h5:hover .headerlink:after,.rst-content h6:hover .headerlink:after,.rst-content dl dt:hover .headerlink:after,.rst-content p.caption:hover .headerlink:after,.rst-content table>caption:hover .headerlink:after,.rst-content .code-block-caption:hover .headerlink:after{visibility:visible}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .footnote-reference,.rst-content .citation-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content table.docutils,.rst-content table.field-list{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption{padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list th{margin:0;overflow:visible}.rst-content table.docutils td{padding:10px 31px}.rst-content table.docutils th,.rst-content table.field-list th{padding:11px 31px}.rst-content table.docutils td:first-child,.rst-content table.field-list td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead{text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th{border-bottom:solid 1px rgba(81,80,79,.3);border-left:solid 1px rgba(81,80,79,.3)}.rst-content table.docutils thead th p,.rst-content table.field-list thead th p{font-weight:700;font-size:18px;color:#51504f;line-height:1.33;margin-bottom:0}.rst-content table.docutils td,.rst-content table.field-list td{background-color:transparent;vertical-align:middle}.rst-content td p:last-child,.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child{margin-bottom:0}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td{background-color:rgba(112,112,112,.05)}.rst-content table.docutils{border:1px solid rgba(81,80,79,.3)}.rst-content table.docutils td{border-bottom:1px solid rgba(81,80,79,.3);border-left:1px solid rgba(81,80,79,.3)}.rst-content table.docutils tbody>tr:last-child td{border-bottom-width:0}.rst-content .wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.rst-content .wy-table-responsive table{margin-bottom:0!important}.rst-content .wy-table-responsive table td,.rst-content .wy-table-responsive table th{white-space:nowrap}.rst-content code big,.rst-content tt em,.rst-content code em{font-size:100%!important;line-height:normal}.rst-content code.literal{color:#e74c3c}.rst-content code.xref,.rst-content a code{font-weight:700;color:#707070}.rst-content pre,.rst-content kbd{font-family:roboto mono,monospace}.rst-content kbd{background-color:inherit;color:inherit;-webkit-box-shadow:none;box-shadow:none;border:none;font-size:100%}.rst-content a code{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px;word-break:break-word}.rst-content dl p,.rst-content dl table,.rst-content dl ul,.rst-content dl ol{margin-bottom:12px!important}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl:not(.docutils){margin-bottom:24px}.rst-content dl:not(.docutils) dt{font-family:roboto mono,monospace;display:table;margin:6px 0;font-size:100%;line-height:1.63;background:#f3fbff;color:#51504f;border-top:solid 4px #68d1ff;padding:8px 10px;position:relative}@media(max-width:768px){.rst-content dl:not(.docutils) dt{font-size:10px}}.rst-content dl:not(.docutils) dt:before{color:#68d1ff}.rst-content dl:not(.docutils) dt .headerlink{color:#707070;font-size:100%!important}.rst-content dl:not(.docutils) dt .fn-backref{color:#0cb6ff}.rst-content dl:not(.docutils) dl dt{margin-bottom:6px;border:none;border-left:solid 8px #a6a6a6;background:#f8f8f8;color:#707070}.rst-content dl:not(.docutils) dl dt .headerlink{color:#707070;font-size:100%!important}.rst-content dl:not(.docutils) dt:first-child{margin-top:0}.rst-content dl:not(.docutils) code{font-weight:700}.rst-content dl:not(.docutils) code.descname,.rst-content dl:not(.docutils) code.descclassname{background-color:transparent;border:none;padding:0;font-size:100%!important}.rst-content dl:not(.docutils) code.descname{font-weight:700}.rst-content dl:not(.docutils) .optional{display:inline-block;padding:0 4px;color:#51504f;font-weight:700}.rst-content dl:not(.docutils) .property{display:inline-block;padding-right:8px}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content .versionmodified{font-style:italic}.rst-content .example-header{position:relative;background:#017cee;padding:8px 16px;margin-bottom:0}.rst-content .example-block-wrapper pre{margin:0;width:unset;border-top-left-radius:0;border-top-right-radius:0}.rst-content .example-header--with-button{padding-right:166px}@media(max-width:768px){.rst-content .example-header--with-button{padding-right:100px}}.rst-content .example-header:after{content:'';display:table;clear:both}.rst-content .example-title{display:block;padding:4px;margin-right:16px;color:#fff;overflow-x:auto}@media(max-width:768px){.rst-content .example-title{overflow-wrap:initial;font-size:12px}}.rst-content .example-header-button{top:8px;right:16px;position:absolute}.rst-content .example-header+.highlight-python{margin-top:0!important}.rst-content .viewcode-button{display:inline-block;padding:8px 16px;border:0;margin:0;color:#fff;font-weight:700;line-height:1;text-decoration:underline;text-overflow:ellipsis;overflow:hidden;text-transform:lowercase;vertical-align:middle;white-space:nowrap}@media(max-width:768px){.rst-content .viewcode-button{font-size:12px;padding:7px 0}}.rst-content .viewcode-button:visited{color:#404040}.rst-content .viewcode-button:hover,.rst-content .viewcode-button:focus{color:#404040}@media(min-width:1024px){.rst-content .section::before{display:block;content:" ";margin-top:-83px;height:83px;visibility:hidden}}.content-drawer-wrapper{display:none}@media(max-width:1280px){.content-drawer-wrapper{display:block;margin-bottom:30px}}.content-drawer-wrapper .navbar{-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;left:0}.content-drawer-wrapper .navbar--hidden{display:none}.content-drawer-container{position:fixed;top:77px;left:0;width:100%;height:100%;background-color:#fff;-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);-o-transform:translateX(-100%);transform:translateX(-100%);-webkit-transition:.2s ease-out;-o-transition:.2s ease-out;transition:.2s ease-out;z-index:100}.content-drawer-container--open{-webkit-transform:translateX(0);-ms-transform:translateX(0);-o-transform:translateX(0);transform:translateX(0)}.content-drawer{padding:20px 40px}.content-drawer__toggle-button{border:none;background:0 0;padding:0;position:relative;width:26px;height:20px}.content-drawer__toggle-button--icon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;visibility:hidden;opacity:0;-webkit-transition:.2s ease-out;-o-transition:.2s ease-out;transition:.2s ease-out}.content-drawer__toggle-button--icon svg{margin-right:10px}.content-drawer__toggle-button--icon.visible{visibility:visible;opacity:1}.dropdown-menu{font-family:roboto,sans-serif}.dropdown-toggle::after{color:#51504f}.sidebar__version-selector{margin-bottom:22px}.chroma,.highlight{background-color:#fff}.chroma .lntd,.highlight .lntd{vertical-align:top;padding:0;margin:0;border:0}.chroma .lntable,.highlight .lntable{border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block}.chroma .hl,.highlight .hl{display:block;width:100%;background-color:#ffc}.chroma .lnt,.chroma .ln,.highlight .lnt,.highlight .ln{margin-right:.4em;padding:0 .4em;color:#7f7f7f}.chroma .k,.chroma .kc,.chroma .kd,.chroma .kn,.chroma .kp,.chroma .kr,.highlight .k,.highlight .kc,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr{color:#00f}.chroma .kt,.chroma .nc,.highlight .kt,.highlight .nc{color:#2b91af}.chroma .s,.chroma .sa,.chroma .sb,.chroma .sc,.chroma .dl,.chroma .sd,.chroma .s2,.chroma .se,.chroma .sh,.chroma .si,.chroma .sx,.chroma .sr,.chroma .s1,.chroma .ss,.highlight .s,.highlight .sa,.highlight .sb,.highlight .sc,.highlight .dl,.highlight .sd,.highlight .s2,.highlight .se,.highlight .sh,.highlight .si,.highlight .sx,.highlight .sr,.highlight .s1,.highlight .ss{color:#a31515}.chroma .ow,.highlight .ow{color:#00f}.chroma .c,.chroma .ch,.chroma .cm,.chroma .c1,.chroma .cs,.highlight .c,.highlight .ch,.highlight .cm,.highlight .c1,.highlight .cs{color:green}.chroma .cp,.chroma .cpf,.highlight .cp,.highlight .cpf{color:#00f}.chroma .ge,.highlight .ge{font-style:italic}.chroma .gh,.chroma .gp,.chroma .gs,.chroma .gu,.highlight .gh,.highlight .gp,.highlight .gs,.highlight .gu{font-weight:700}pre{margin:40px 0;padding:16px 20px;border:solid 1px #cbcbcb;border-radius:5px;width:100%}.share-section--icons-wrapper{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.share-section--icon{margin-right:12px;cursor:pointer}.four-oh-four{height:-webkit-calc(100vh - 123px);height:calc(100vh - 123px);position:relative}.four-oh-four__text-container{position:relative;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);-o-transform:translate(-50%,-50%);transform:translate(-50%,-50%);text-align:center} \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/_gen/css/main.min.css b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/_gen/css/main.min.css new file mode 100644 index 00000000000..603f3cb39ff --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/_gen/css/main.min.css @@ -0,0 +1,7 @@ +@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,700,700i";@fa-font-path:"../webfonts";/*!* Bootstrap v4.1.3 (https://getbootstrap.com/) +* Copyright 2011-2018 The Bootstrap Authors +* Copyright 2011-2018 Twitter, Inc. +* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)*/:root{--blue: #72A1E5;--indigo: #6610f2;--purple: #6f42c1;--pink: #e83e8c;--red: #dc3545;--orange: #BA5A31;--yellow: #ffc107;--green: #28a745;--teal: #20c997;--cyan: #17a2b8;--white: #fff;--gray: #888;--gray-dark: #333;--primary: #30638E;--secondary: #FFA630;--success: #3772FF;--info: #C0E0DE;--warning: #ED6A5A;--danger: #ED6A5A;--light: #D3F3EE;--dark: #403F4C;--breakpoint-xs: 0;--breakpoint-sm: 576px;--breakpoint-md: 768px;--breakpoint-lg: 992px;--breakpoint-xl: 1200px;--font-family-sans-serif: "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}*,*::before,*::after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:rgba(0,0,0,0)}@-ms-viewport{width:device-width;}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:open sans,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;font-size:1rem;font-weight:400;line-height:1.5;color:#222;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[title],abbr[data-original-title]{text-decoration:underline;-webkit-text-decoration:underline dotted;-moz-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#3176d9;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#1e53a0;text-decoration:none}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):hover,a:not([href]):not([tabindex]):focus{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}pre,code,kbd,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,liberation mono,courier new,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#888;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}button,html [type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{padding:0;border-style:none}input[type=radio],input[type=checkbox]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{margin-bottom:.5rem;font-family:inherit;font-weight:500;line-height:1.2;color:inherit}h1,.h1{font-size:2.25rem}h2,.h2{font-size:2rem}h3,.h3{font-size:1.5rem}h4,.h4{font-size:1.35rem}h5,.h5{font-size:1.15rem}h6,.h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:3rem;font-weight:700;line-height:1.2}.display-2{font-size:2.5rem;font-weight:700;line-height:1.2}.display-3{font-size:2rem;font-weight:700;line-height:1.2}.display-4{font-size:1.75rem;font-weight:700;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}small,.small{font-size:80%;font-weight:400}mark,.mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#888}.blockquote-footer::before{content:"\2014 \00A0"}.img-fluid,.td-content img{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075);max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#888}code{font-size:87.5%;color:#c97300;word-break:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#222;border-radius:.2rem;-webkit-box-shadow:inset 0 -.1rem 0 rgba(0,0,0,.25);box-shadow:inset 0 -.1rem 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;font-size:87.5%;color:#222}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media(min-width:576px){.container{max-width:540px}}@media(min-width:768px){.container{max-width:720px}}@media(min-width:992px){.container{max-width:960px}}@media(min-width:1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-11,.col-12,.col,.col-auto,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm,.col-sm-auto,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-md,.col-md-auto,.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg,.col-lg-auto,.col-xl-1,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl,.col-xl-auto{position:relative;width:100%;min-height:1px;padding-right:15px;padding-left:15px}.col{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333333%;-ms-flex:0 0 8.33333333%;flex:0 0 8.33333333%;max-width:8.33333333%}.col-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66666667%;-ms-flex:0 0 16.66666667%;flex:0 0 16.66666667%;max-width:16.66666667%}.col-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333333%;-ms-flex:0 0 33.33333333%;flex:0 0 33.33333333%;max-width:33.33333333%}.col-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66666667%;-ms-flex:0 0 41.66666667%;flex:0 0 41.66666667%;max-width:41.66666667%}.col-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333333%;-ms-flex:0 0 58.33333333%;flex:0 0 58.33333333%;max-width:58.33333333%}.col-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66666667%;-ms-flex:0 0 66.66666667%;flex:0 0 66.66666667%;max-width:66.66666667%}.col-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333333%;-ms-flex:0 0 83.33333333%;flex:0 0 83.33333333%;max-width:83.33333333%}.col-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66666667%;-ms-flex:0 0 91.66666667%;flex:0 0 91.66666667%;max-width:91.66666667%}.col-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.order-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.order-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.order-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.order-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.order-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.order-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.order-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.order-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.order-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.order-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.order-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.order-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.order-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.order-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}@media(min-width:576px){.col-sm{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-sm-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333333%;-ms-flex:0 0 8.33333333%;flex:0 0 8.33333333%;max-width:8.33333333%}.col-sm-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66666667%;-ms-flex:0 0 16.66666667%;flex:0 0 16.66666667%;max-width:16.66666667%}.col-sm-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333333%;-ms-flex:0 0 33.33333333%;flex:0 0 33.33333333%;max-width:33.33333333%}.col-sm-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66666667%;-ms-flex:0 0 41.66666667%;flex:0 0 41.66666667%;max-width:41.66666667%}.col-sm-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333333%;-ms-flex:0 0 58.33333333%;flex:0 0 58.33333333%;max-width:58.33333333%}.col-sm-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66666667%;-ms-flex:0 0 66.66666667%;flex:0 0 66.66666667%;max-width:66.66666667%}.col-sm-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333333%;-ms-flex:0 0 83.33333333%;flex:0 0 83.33333333%;max-width:83.33333333%}.col-sm-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66666667%;-ms-flex:0 0 91.66666667%;flex:0 0 91.66666667%;max-width:91.66666667%}.col-sm-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.order-sm-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.order-sm-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.order-sm-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.order-sm-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.order-sm-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.order-sm-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.order-sm-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.order-sm-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.order-sm-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.order-sm-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.order-sm-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.order-sm-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.order-sm-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.order-sm-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}}@media(min-width:768px){.col-md{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-md-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333333%;-ms-flex:0 0 8.33333333%;flex:0 0 8.33333333%;max-width:8.33333333%}.col-md-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66666667%;-ms-flex:0 0 16.66666667%;flex:0 0 16.66666667%;max-width:16.66666667%}.col-md-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333333%;-ms-flex:0 0 33.33333333%;flex:0 0 33.33333333%;max-width:33.33333333%}.col-md-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66666667%;-ms-flex:0 0 41.66666667%;flex:0 0 41.66666667%;max-width:41.66666667%}.col-md-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333333%;-ms-flex:0 0 58.33333333%;flex:0 0 58.33333333%;max-width:58.33333333%}.col-md-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66666667%;-ms-flex:0 0 66.66666667%;flex:0 0 66.66666667%;max-width:66.66666667%}.col-md-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333333%;-ms-flex:0 0 83.33333333%;flex:0 0 83.33333333%;max-width:83.33333333%}.col-md-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66666667%;-ms-flex:0 0 91.66666667%;flex:0 0 91.66666667%;max-width:91.66666667%}.col-md-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.order-md-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.order-md-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.order-md-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.order-md-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.order-md-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.order-md-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.order-md-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.order-md-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.order-md-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.order-md-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.order-md-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.order-md-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.order-md-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.order-md-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}}@media(min-width:992px){.col-lg{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-lg-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333333%;-ms-flex:0 0 8.33333333%;flex:0 0 8.33333333%;max-width:8.33333333%}.col-lg-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66666667%;-ms-flex:0 0 16.66666667%;flex:0 0 16.66666667%;max-width:16.66666667%}.col-lg-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333333%;-ms-flex:0 0 33.33333333%;flex:0 0 33.33333333%;max-width:33.33333333%}.col-lg-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66666667%;-ms-flex:0 0 41.66666667%;flex:0 0 41.66666667%;max-width:41.66666667%}.col-lg-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333333%;-ms-flex:0 0 58.33333333%;flex:0 0 58.33333333%;max-width:58.33333333%}.col-lg-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66666667%;-ms-flex:0 0 66.66666667%;flex:0 0 66.66666667%;max-width:66.66666667%}.col-lg-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333333%;-ms-flex:0 0 83.33333333%;flex:0 0 83.33333333%;max-width:83.33333333%}.col-lg-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66666667%;-ms-flex:0 0 91.66666667%;flex:0 0 91.66666667%;max-width:91.66666667%}.col-lg-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.order-lg-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.order-lg-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.order-lg-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.order-lg-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.order-lg-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.order-lg-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.order-lg-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.order-lg-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.order-lg-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.order-lg-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.order-lg-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.order-lg-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.order-lg-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.order-lg-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}}@media(min-width:1200px){.col-xl{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-xl-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333333%;-ms-flex:0 0 8.33333333%;flex:0 0 8.33333333%;max-width:8.33333333%}.col-xl-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66666667%;-ms-flex:0 0 16.66666667%;flex:0 0 16.66666667%;max-width:16.66666667%}.col-xl-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333333%;-ms-flex:0 0 33.33333333%;flex:0 0 33.33333333%;max-width:33.33333333%}.col-xl-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66666667%;-ms-flex:0 0 41.66666667%;flex:0 0 41.66666667%;max-width:41.66666667%}.col-xl-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333333%;-ms-flex:0 0 58.33333333%;flex:0 0 58.33333333%;max-width:58.33333333%}.col-xl-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66666667%;-ms-flex:0 0 66.66666667%;flex:0 0 66.66666667%;max-width:66.66666667%}.col-xl-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333333%;-ms-flex:0 0 83.33333333%;flex:0 0 83.33333333%;max-width:83.33333333%}.col-xl-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66666667%;-ms-flex:0 0 91.66666667%;flex:0 0 91.66666667%;max-width:91.66666667%}.col-xl-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.order-xl-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.order-xl-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.order-xl-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.order-xl-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.order-xl-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.order-xl-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.order-xl-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.order-xl-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.order-xl-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.order-xl-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.order-xl-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.order-xl-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.order-xl-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.order-xl-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}}.table,.td-box .row.section>table,.td-content>table{width:100%;margin-bottom:1rem;background-color:transparent}.table th,.td-box .row.section>table th,.td-content>table th,.table td,.td-box .row.section>table td,.td-content>table td{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th,.td-box .row.section>table thead th,.td-content>table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody,.td-box .row.section>table tbody+tbody,.td-content>table tbody+tbody{border-top:2px solid #dee2e6}.table .table,.td-box .row.section>table .table,.td-content>table .table,.table .td-box .row.section>table,.td-box .table .row.section>table,.td-box .row.section>table .row.section>table,.td-content>table .td-box .row.section>table,.td-box .td-content>table .row.section>table,.table .td-content>table,.td-box .row.section>table .td-content>table,.td-content>table .td-content>table{background-color:#fff}.table-sm th,.table-sm td{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered th,.table-bordered td{border:1px solid #dee2e6}.table-bordered thead th,.table-bordered thead td{border-bottom-width:2px}.table-borderless th,.table-borderless td,.table-borderless thead th,.table-borderless tbody+tbody{border:0}.table-striped tbody tr:nth-of-type(odd),.td-box .row.section>table tbody tr:nth-of-type(odd),.td-content>table tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>th,.table-primary>td{background-color:#c5d3df}.table-hover .table-primary:hover{background-color:#b5c7d6}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#b5c7d6}.table-secondary,.table-secondary>th,.table-secondary>td{background-color:#ffe6c5}.table-hover .table-secondary:hover{background-color:#ffdbac}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#ffdbac}.table-success,.table-success>th,.table-success>td{background-color:#c7d8ff}.table-hover .table-success:hover{background-color:#aec6ff}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#aec6ff}.table-info,.table-info>th,.table-info>td{background-color:#edf6f6}.table-hover .table-info:hover{background-color:#dceeee}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#dceeee}.table-warning,.table-warning>th,.table-warning>td{background-color:#fad5d1}.table-hover .table-warning:hover{background-color:#f8c0ba}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#f8c0ba}.table-danger,.table-danger>th,.table-danger>td{background-color:#fad5d1}.table-hover .table-danger:hover{background-color:#f8c0ba}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f8c0ba}.table-light,.table-light>th,.table-light>td{background-color:#f3fcfa}.table-hover .table-light:hover{background-color:#dff7f2}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#dff7f2}.table-dark,.table-dark>th,.table-dark>td{background-color:#cac9cd}.table-hover .table-dark:hover{background-color:#bdbcc1}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#bdbcc1}.table-active,.table-active>th,.table-active>td{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th,.td-box .row.section>table .thead-dark th,.td-content>table .thead-dark th{color:#fff;background-color:#222;border-color:#353535}.table .thead-light th,.td-box .row.section>table .thead-light th,.td-content>table .thead-light th{color:#495057;background-color:#eee;border-color:#dee2e6}.table-dark{color:#fff;background-color:#222}.table-dark th,.table-dark td,.table-dark thead th{border-color:#353535}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd),.td-box .row.section>table.table-dark tbody tr:nth-of-type(odd),.td-content>table.table-dark tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{background-color:rgba(255,255,255,.075)}@media(max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-sm>.table-bordered{border:0}}@media(max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-md>.table-bordered{border:0}}@media(max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-lg>.table-bordered{border:0}}@media(max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-xl>.table-bordered{border:0}}.table-responsive,.td-box .row.section>table,.td-content>table{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive>.table-bordered,.td-box .row.section>table>.table-bordered,.td-content>table>.table-bordered{border:0}.form-control{display:block;width:100%;height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px);padding:.375rem .75rem;font-size:1rem;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border-radius:.25rem;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media screen and (prefers-reduced-motion:reduce){.form-control{-webkit-transition:none;-o-transition:none;transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#6fa3ce;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(48,99,142,.25);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(48,99,142,.25)}.form-control::-webkit-input-placeholder{color:#888;opacity:1}.form-control::-moz-placeholder{color:#888;opacity:1}.form-control:-ms-input-placeholder{color:#888;opacity:1}.form-control::placeholder{color:#888;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#eee;opacity:1}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:-webkit-calc(0.375rem + 1px);padding-top:calc(0.375rem + 1px);padding-bottom:-webkit-calc(0.375rem + 1px);padding-bottom:calc(0.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:-webkit-calc(0.5rem + 1px);padding-top:calc(0.5rem + 1px);padding-bottom:-webkit-calc(0.5rem + 1px);padding-bottom:calc(0.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:-webkit-calc(0.25rem + 1px);padding-top:calc(0.25rem + 1px);padding-bottom:-webkit-calc(0.25rem + 1px);padding-bottom:calc(0.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding-top:.375rem;padding-bottom:.375rem;margin-bottom:0;line-height:1.5;color:#222;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{height:-webkit-calc(1.8125rem + 2px);height:calc(1.8125rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:-webkit-calc(2.875rem + 2px);height:calc(2.875rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[size],select.form-control[multiple]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label{color:#888}.form-check-label{margin-bottom:0}.form-check-inline{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#3772ff}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(55,114,255,.9);border-radius:.25rem}.was-validated .form-control:valid,.form-control.is-valid,.was-validated .custom-select:valid,.custom-select.is-valid{border-color:#3772ff}.was-validated .form-control:valid:focus,.form-control.is-valid:focus,.was-validated .custom-select:valid:focus,.custom-select.is-valid:focus{border-color:#3772ff;-webkit-box-shadow:0 0 0 .2rem rgba(55,114,255,.25);box-shadow:0 0 0 .2rem rgba(55,114,255,.25)}.was-validated .form-control:valid~.valid-feedback,.was-validated .form-control:valid~.valid-tooltip,.form-control.is-valid~.valid-feedback,.form-control.is-valid~.valid-tooltip,.was-validated .custom-select:valid~.valid-feedback,.was-validated .custom-select:valid~.valid-tooltip,.custom-select.is-valid~.valid-feedback,.custom-select.is-valid~.valid-tooltip{display:block}.was-validated .form-control-file:valid~.valid-feedback,.was-validated .form-control-file:valid~.valid-tooltip,.form-control-file.is-valid~.valid-feedback,.form-control-file.is-valid~.valid-tooltip{display:block}.was-validated .form-check-input:valid~.form-check-label,.form-check-input.is-valid~.form-check-label{color:#3772ff}.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip,.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip{display:block}.was-validated .custom-control-input:valid~.custom-control-label,.custom-control-input.is-valid~.custom-control-label{color:#3772ff}.was-validated .custom-control-input:valid~.custom-control-label::before,.custom-control-input.is-valid~.custom-control-label::before{background-color:#b7ccff}.was-validated .custom-control-input:valid~.valid-feedback,.was-validated .custom-control-input:valid~.valid-tooltip,.custom-control-input.is-valid~.valid-feedback,.custom-control-input.is-valid~.valid-tooltip{display:block}.was-validated .custom-control-input:valid:checked~.custom-control-label::before,.custom-control-input.is-valid:checked~.custom-control-label::before{background:#6a96ff -webkit-gradient(linear,left top,left bottom,from(#80a6ff),to(#6a96ff)) repeat-x;background:#6a96ff -webkit-linear-gradient(top,#80a6ff,#6a96ff) repeat-x;background:#6a96ff -o-linear-gradient(top,#80a6ff,#6a96ff) repeat-x;background:#6a96ff linear-gradient(180deg,#80a6ff,#6a96ff) repeat-x}.was-validated .custom-control-input:valid:focus~.custom-control-label::before,.custom-control-input.is-valid:focus~.custom-control-label::before{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(55,114,255,.25);box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(55,114,255,.25)}.was-validated .custom-file-input:valid~.custom-file-label,.custom-file-input.is-valid~.custom-file-label{border-color:#3772ff}.was-validated .custom-file-input:valid~.custom-file-label::after,.custom-file-input.is-valid~.custom-file-label::after{border-color:inherit}.was-validated .custom-file-input:valid~.valid-feedback,.was-validated .custom-file-input:valid~.valid-tooltip,.custom-file-input.is-valid~.valid-feedback,.custom-file-input.is-valid~.valid-tooltip{display:block}.was-validated .custom-file-input:valid:focus~.custom-file-label,.custom-file-input.is-valid:focus~.custom-file-label{-webkit-box-shadow:0 0 0 .2rem rgba(55,114,255,.25);box-shadow:0 0 0 .2rem rgba(55,114,255,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#ed6a5a}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(237,106,90,.9);border-radius:.25rem}.was-validated .form-control:invalid,.form-control.is-invalid,.was-validated .custom-select:invalid,.custom-select.is-invalid{border-color:#ed6a5a}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus,.was-validated .custom-select:invalid:focus,.custom-select.is-invalid:focus{border-color:#ed6a5a;-webkit-box-shadow:0 0 0 .2rem rgba(237,106,90,.25);box-shadow:0 0 0 .2rem rgba(237,106,90,.25)}.was-validated .form-control:invalid~.invalid-feedback,.was-validated .form-control:invalid~.invalid-tooltip,.form-control.is-invalid~.invalid-feedback,.form-control.is-invalid~.invalid-tooltip,.was-validated .custom-select:invalid~.invalid-feedback,.was-validated .custom-select:invalid~.invalid-tooltip,.custom-select.is-invalid~.invalid-feedback,.custom-select.is-invalid~.invalid-tooltip{display:block}.was-validated .form-control-file:invalid~.invalid-feedback,.was-validated .form-control-file:invalid~.invalid-tooltip,.form-control-file.is-invalid~.invalid-feedback,.form-control-file.is-invalid~.invalid-tooltip{display:block}.was-validated .form-check-input:invalid~.form-check-label,.form-check-input.is-invalid~.form-check-label{color:#ed6a5a}.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip,.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip{display:block}.was-validated .custom-control-input:invalid~.custom-control-label,.custom-control-input.is-invalid~.custom-control-label{color:#ed6a5a}.was-validated .custom-control-input:invalid~.custom-control-label::before,.custom-control-input.is-invalid~.custom-control-label::before{background-color:#fad2cd}.was-validated .custom-control-input:invalid~.invalid-feedback,.was-validated .custom-control-input:invalid~.invalid-tooltip,.custom-control-input.is-invalid~.invalid-feedback,.custom-control-input.is-invalid~.invalid-tooltip{display:block}.was-validated .custom-control-input:invalid:checked~.custom-control-label::before,.custom-control-input.is-invalid:checked~.custom-control-label::before{background:#f29488 -webkit-gradient(linear,left top,left bottom,from(#f4a49a),to(#f29488)) repeat-x;background:#f29488 -webkit-linear-gradient(top,#f4a49a,#f29488) repeat-x;background:#f29488 -o-linear-gradient(top,#f4a49a,#f29488) repeat-x;background:#f29488 linear-gradient(180deg,#f4a49a,#f29488) repeat-x}.was-validated .custom-control-input:invalid:focus~.custom-control-label::before,.custom-control-input.is-invalid:focus~.custom-control-label::before{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(237,106,90,.25);box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(237,106,90,.25)}.was-validated .custom-file-input:invalid~.custom-file-label,.custom-file-input.is-invalid~.custom-file-label{border-color:#ed6a5a}.was-validated .custom-file-input:invalid~.custom-file-label::after,.custom-file-input.is-invalid~.custom-file-label::after{border-color:inherit}.was-validated .custom-file-input:invalid~.invalid-feedback,.was-validated .custom-file-input:invalid~.invalid-tooltip,.custom-file-input.is-invalid~.invalid-feedback,.custom-file-input.is-invalid~.invalid-tooltip{display:block}.was-validated .custom-file-input:invalid:focus~.custom-file-label,.custom-file-input.is-invalid:focus~.custom-file-label{-webkit-box-shadow:0 0 0 .2rem rgba(237,106,90,.25);box-shadow:0 0 0 .2rem rgba(237,106,90,.25)}.form-inline{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media(min-width:576px){.form-inline label{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .input-group,.form-inline .custom-select{width:auto}.form-inline .form-check{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;text-align:center;white-space:nowrap;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media screen and (prefers-reduced-motion:reduce){.btn{-webkit-transition:none;-o-transition:none;transition:none}}.btn:hover,.btn:focus{text-decoration:none}.btn:focus,.btn.focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(48,99,142,.25);box-shadow:0 0 0 .2rem rgba(48,99,142,.25)}.btn.disabled,.btn:disabled{opacity:.65;-webkit-box-shadow:none;box-shadow:none}.btn:not(:disabled):not(.disabled){cursor:pointer}.btn:not(:disabled):not(.disabled):active,.btn:not(:disabled):not(.disabled).active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn:not(:disabled):not(.disabled):active:focus,.btn:not(:disabled):not(.disabled).active:focus{-webkit-box-shadow:0 0 0 .2rem rgba(48,99,142,.25),inset 0 3px 5px rgba(0,0,0,.125);box-shadow:0 0 0 .2rem rgba(48,99,142,.25),inset 0 3px 5px rgba(0,0,0,.125)}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x;border-color:#30638e;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-primary:hover{color:#fff;background:#264f71 -webkit-gradient(linear,left top,left bottom,from(#476987),to(#264f71)) repeat-x;background:#264f71 -webkit-linear-gradient(top,#476987,#264f71) repeat-x;background:#264f71 -o-linear-gradient(top,#476987,#264f71) repeat-x;background:#264f71 linear-gradient(180deg,#476987,#264f71) repeat-x;border-color:#234868}.btn-primary:focus,.btn-primary.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(48,99,142,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(48,99,142,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#30638e;border-color:#30638e}.btn-primary:not(:disabled):not(.disabled):active,.btn-primary:not(:disabled):not(.disabled).active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#234868;background-image:none;border-color:#20425e}.btn-primary:not(:disabled):not(.disabled):active:focus,.btn-primary:not(:disabled):not(.disabled).active:focus,.show>.btn-primary.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(48,99,142,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(48,99,142,.5)}.btn-secondary{color:#fff;background:#FFA630 -webkit-gradient(linear,left top,left bottom,from(#ffb34f),to(#FFA630)) repeat-x;background:#ffa630 -webkit-linear-gradient(top,#ffb34f,#FFA630) repeat-x;background:#ffa630 -o-linear-gradient(top,#ffb34f,#FFA630) repeat-x;background:#ffa630 linear-gradient(180deg,#ffb34f,#FFA630) repeat-x;border-color:#ffa630;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-secondary:hover{color:#fff;background:#ff960a -webkit-gradient(linear,left top,left bottom,from(#ffa52f),to(#ff960a)) repeat-x;background:#ff960a -webkit-linear-gradient(top,#ffa52f,#ff960a) repeat-x;background:#ff960a -o-linear-gradient(top,#ffa52f,#ff960a) repeat-x;background:#ff960a linear-gradient(180deg,#ffa52f,#ff960a) repeat-x;border-color:#fc9000}.btn-secondary:focus,.btn-secondary.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(255,166,48,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(255,166,48,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#ffa630;border-color:#ffa630}.btn-secondary:not(:disabled):not(.disabled):active,.btn-secondary:not(:disabled):not(.disabled).active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#fc9000;background-image:none;border-color:#ef8800}.btn-secondary:not(:disabled):not(.disabled):active:focus,.btn-secondary:not(:disabled):not(.disabled).active:focus,.show>.btn-secondary.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(255,166,48,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(255,166,48,.5)}.btn-success{color:#fff;background:#3772FF -webkit-gradient(linear,left top,left bottom,from(#5587ff),to(#3772FF)) repeat-x;background:#3772ff -webkit-linear-gradient(top,#5587ff,#3772FF) repeat-x;background:#3772ff -o-linear-gradient(top,#5587ff,#3772FF) repeat-x;background:#3772ff linear-gradient(180deg,#5587ff,#3772FF) repeat-x;border-color:#3772ff;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-success:hover{color:#fff;background:#1157ff -webkit-gradient(linear,left top,left bottom,from(#3470ff),to(#1157ff)) repeat-x;background:#1157ff -webkit-linear-gradient(top,#3470ff,#1157ff) repeat-x;background:#1157ff -o-linear-gradient(top,#3470ff,#1157ff) repeat-x;background:#1157ff linear-gradient(180deg,#3470ff,#1157ff) repeat-x;border-color:#044eff}.btn-success:focus,.btn-success.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(55,114,255,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(55,114,255,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#3772ff;border-color:#3772ff}.btn-success:not(:disabled):not(.disabled):active,.btn-success:not(:disabled):not(.disabled).active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#044eff;background-image:none;border-color:#0049f6}.btn-success:not(:disabled):not(.disabled):active:focus,.btn-success:not(:disabled):not(.disabled).active:focus,.show>.btn-success.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(55,114,255,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(55,114,255,.5)}.btn-info{color:#222;background:#C0E0DE -webkit-gradient(linear,left top,left bottom,from(#c9e5e3),to(#C0E0DE)) repeat-x;background:#c0e0de -webkit-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x;background:#c0e0de -o-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x;background:#c0e0de linear-gradient(180deg,#c9e5e3,#C0E0DE) repeat-x;border-color:#c0e0de;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-info:hover{color:#fff;background:#a6d3d1 -webkit-gradient(linear,left top,left bottom,from(#b4dad8),to(#a6d3d1)) repeat-x;background:#a6d3d1 -webkit-linear-gradient(top,#b4dad8,#a6d3d1) repeat-x;background:#a6d3d1 -o-linear-gradient(top,#b4dad8,#a6d3d1) repeat-x;background:#a6d3d1 linear-gradient(180deg,#b4dad8,#a6d3d1) repeat-x;border-color:#9ecfcc}.btn-info:focus,.btn-info.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(192,224,222,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(192,224,222,.5)}.btn-info.disabled,.btn-info:disabled{color:#222;background-color:#c0e0de;border-color:#c0e0de}.btn-info:not(:disabled):not(.disabled):active,.btn-info:not(:disabled):not(.disabled).active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#9ecfcc;background-image:none;border-color:#95cbc8}.btn-info:not(:disabled):not(.disabled):active:focus,.btn-info:not(:disabled):not(.disabled).active:focus,.show>.btn-info.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(192,224,222,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(192,224,222,.5)}.btn-warning{color:#fff;background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x;border-color:#ed6a5a;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-warning:hover{color:#fff;background:#e94b38 -webkit-gradient(linear,left top,left bottom,from(#ed6655),to(#e94b38)) repeat-x;background:#e94b38 -webkit-linear-gradient(top,#ed6655,#e94b38) repeat-x;background:#e94b38 -o-linear-gradient(top,#ed6655,#e94b38) repeat-x;background:#e94b38 linear-gradient(180deg,#ed6655,#e94b38) repeat-x;border-color:#e8402c}.btn-warning:focus,.btn-warning.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(237,106,90,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(237,106,90,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#fff;background-color:#ed6a5a;border-color:#ed6a5a}.btn-warning:not(:disabled):not(.disabled):active,.btn-warning:not(:disabled):not(.disabled).active,.show>.btn-warning.dropdown-toggle{color:#fff;background-color:#e8402c;background-image:none;border-color:#e73621}.btn-warning:not(:disabled):not(.disabled):active:focus,.btn-warning:not(:disabled):not(.disabled).active:focus,.show>.btn-warning.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5)}.btn-danger{color:#fff;background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x;border-color:#ed6a5a;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger:hover{color:#fff;background:#e94b38 -webkit-gradient(linear,left top,left bottom,from(#ed6655),to(#e94b38)) repeat-x;background:#e94b38 -webkit-linear-gradient(top,#ed6655,#e94b38) repeat-x;background:#e94b38 -o-linear-gradient(top,#ed6655,#e94b38) repeat-x;background:#e94b38 linear-gradient(180deg,#ed6655,#e94b38) repeat-x;border-color:#e8402c}.btn-danger:focus,.btn-danger.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(237,106,90,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(237,106,90,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#ed6a5a;border-color:#ed6a5a}.btn-danger:not(:disabled):not(.disabled):active,.btn-danger:not(:disabled):not(.disabled).active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#e8402c;background-image:none;border-color:#e73621}.btn-danger:not(:disabled):not(.disabled):active:focus,.btn-danger:not(:disabled):not(.disabled).active:focus,.show>.btn-danger.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5)}.btn-light{color:#222;background:#D3F3EE -webkit-gradient(linear,left top,left bottom,from(#daf5f1),to(#D3F3EE)) repeat-x;background:#d3f3ee -webkit-linear-gradient(top,#daf5f1,#D3F3EE) repeat-x;background:#d3f3ee -o-linear-gradient(top,#daf5f1,#D3F3EE) repeat-x;background:#d3f3ee linear-gradient(180deg,#daf5f1,#D3F3EE) repeat-x;border-color:#d3f3ee;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-light:hover{color:#222;background:#b5ebe2 -webkit-gradient(linear,left top,left bottom,from(#c0eee7),to(#b5ebe2)) repeat-x;background:#b5ebe2 -webkit-linear-gradient(top,#c0eee7,#b5ebe2) repeat-x;background:#b5ebe2 -o-linear-gradient(top,#c0eee7,#b5ebe2) repeat-x;background:#b5ebe2 linear-gradient(180deg,#c0eee7,#b5ebe2) repeat-x;border-color:#abe8df}.btn-light:focus,.btn-light.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(211,243,238,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(211,243,238,.5)}.btn-light.disabled,.btn-light:disabled{color:#222;background-color:#d3f3ee;border-color:#d3f3ee}.btn-light:not(:disabled):not(.disabled):active,.btn-light:not(:disabled):not(.disabled).active,.show>.btn-light.dropdown-toggle{color:#222;background-color:#abe8df;background-image:none;border-color:#a1e5db}.btn-light:not(:disabled):not(.disabled):active:focus,.btn-light:not(:disabled):not(.disabled).active:focus,.show>.btn-light.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(211,243,238,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(211,243,238,.5)}.btn-dark{color:#fff;background:#403F4C -webkit-gradient(linear,left top,left bottom,from(#5d5c67),to(#403F4C)) repeat-x;background:#403f4c -webkit-linear-gradient(top,#5d5c67,#403F4C) repeat-x;background:#403f4c -o-linear-gradient(top,#5d5c67,#403F4C) repeat-x;background:#403f4c linear-gradient(180deg,#5d5c67,#403F4C) repeat-x;border-color:#403f4c;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-dark:hover{color:#fff;background:#2e2e37 -webkit-gradient(linear,left top,left bottom,from(#4e4d55),to(#2e2e37)) repeat-x;background:#2e2e37 -webkit-linear-gradient(top,#4e4d55,#2e2e37) repeat-x;background:#2e2e37 -o-linear-gradient(top,#4e4d55,#2e2e37) repeat-x;background:#2e2e37 linear-gradient(180deg,#4e4d55,#2e2e37) repeat-x;border-color:#292830}.btn-dark:focus,.btn-dark.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(64,63,76,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(64,63,76,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#403f4c;border-color:#403f4c}.btn-dark:not(:disabled):not(.disabled):active,.btn-dark:not(:disabled):not(.disabled).active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#292830;background-image:none;border-color:#232229}.btn-dark:not(:disabled):not(.disabled):active:focus,.btn-dark:not(:disabled):not(.disabled).active:focus,.show>.btn-dark.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(64,63,76,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(64,63,76,.5)}.btn-outline-primary{color:#30638e;background-color:transparent;background-image:none;border-color:#30638e}.btn-outline-primary:hover{color:#fff;background-color:#30638e;border-color:#30638e}.btn-outline-primary:focus,.btn-outline-primary.focus{-webkit-box-shadow:0 0 0 .2rem rgba(48,99,142,.5);box-shadow:0 0 0 .2rem rgba(48,99,142,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#30638e;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled):active,.btn-outline-primary:not(:disabled):not(.disabled).active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#30638e;border-color:#30638e}.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(48,99,142,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(48,99,142,.5)}.btn-outline-secondary{color:#ffa630;background-color:transparent;background-image:none;border-color:#ffa630}.btn-outline-secondary:hover{color:#fff;background-color:#ffa630;border-color:#ffa630}.btn-outline-secondary:focus,.btn-outline-secondary.focus{-webkit-box-shadow:0 0 0 .2rem rgba(255,166,48,.5);box-shadow:0 0 0 .2rem rgba(255,166,48,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#ffa630;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled):active,.btn-outline-secondary:not(:disabled):not(.disabled).active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#ffa630;border-color:#ffa630}.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(255,166,48,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(255,166,48,.5)}.btn-outline-success{color:#3772ff;background-color:transparent;background-image:none;border-color:#3772ff}.btn-outline-success:hover{color:#fff;background-color:#3772ff;border-color:#3772ff}.btn-outline-success:focus,.btn-outline-success.focus{-webkit-box-shadow:0 0 0 .2rem rgba(55,114,255,.5);box-shadow:0 0 0 .2rem rgba(55,114,255,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#3772ff;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled):active,.btn-outline-success:not(:disabled):not(.disabled).active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#3772ff;border-color:#3772ff}.btn-outline-success:not(:disabled):not(.disabled):active:focus,.btn-outline-success:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-success.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(55,114,255,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(55,114,255,.5)}.btn-outline-info{color:#c0e0de;background-color:transparent;background-image:none;border-color:#c0e0de}.btn-outline-info:hover{color:#222;background-color:#c0e0de;border-color:#c0e0de}.btn-outline-info:focus,.btn-outline-info.focus{-webkit-box-shadow:0 0 0 .2rem rgba(192,224,222,.5);box-shadow:0 0 0 .2rem rgba(192,224,222,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#c0e0de;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled):active,.btn-outline-info:not(:disabled):not(.disabled).active,.show>.btn-outline-info.dropdown-toggle{color:#222;background-color:#c0e0de;border-color:#c0e0de}.btn-outline-info:not(:disabled):not(.disabled):active:focus,.btn-outline-info:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-info.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(192,224,222,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(192,224,222,.5)}.btn-outline-warning{color:#ed6a5a;background-color:transparent;background-image:none;border-color:#ed6a5a}.btn-outline-warning:hover{color:#fff;background-color:#ed6a5a;border-color:#ed6a5a}.btn-outline-warning:focus,.btn-outline-warning.focus{-webkit-box-shadow:0 0 0 .2rem rgba(237,106,90,.5);box-shadow:0 0 0 .2rem rgba(237,106,90,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ed6a5a;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled):active,.btn-outline-warning:not(:disabled):not(.disabled).active,.show>.btn-outline-warning.dropdown-toggle{color:#fff;background-color:#ed6a5a;border-color:#ed6a5a}.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5)}.btn-outline-danger{color:#ed6a5a;background-color:transparent;background-image:none;border-color:#ed6a5a}.btn-outline-danger:hover{color:#fff;background-color:#ed6a5a;border-color:#ed6a5a}.btn-outline-danger:focus,.btn-outline-danger.focus{-webkit-box-shadow:0 0 0 .2rem rgba(237,106,90,.5);box-shadow:0 0 0 .2rem rgba(237,106,90,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#ed6a5a;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled):active,.btn-outline-danger:not(:disabled):not(.disabled).active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#ed6a5a;border-color:#ed6a5a}.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5)}.btn-outline-light{color:#d3f3ee;background-color:transparent;background-image:none;border-color:#d3f3ee}.btn-outline-light:hover{color:#222;background-color:#d3f3ee;border-color:#d3f3ee}.btn-outline-light:focus,.btn-outline-light.focus{-webkit-box-shadow:0 0 0 .2rem rgba(211,243,238,.5);box-shadow:0 0 0 .2rem rgba(211,243,238,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#d3f3ee;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled):active,.btn-outline-light:not(:disabled):not(.disabled).active,.show>.btn-outline-light.dropdown-toggle{color:#222;background-color:#d3f3ee;border-color:#d3f3ee}.btn-outline-light:not(:disabled):not(.disabled):active:focus,.btn-outline-light:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-light.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(211,243,238,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(211,243,238,.5)}.btn-outline-dark{color:#403f4c;background-color:transparent;background-image:none;border-color:#403f4c}.btn-outline-dark:hover{color:#fff;background-color:#403f4c;border-color:#403f4c}.btn-outline-dark:focus,.btn-outline-dark.focus{-webkit-box-shadow:0 0 0 .2rem rgba(64,63,76,.5);box-shadow:0 0 0 .2rem rgba(64,63,76,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#403f4c;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled):active,.btn-outline-dark:not(:disabled):not(.disabled).active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#403f4c;border-color:#403f4c}.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(64,63,76,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(64,63,76,.5)}.btn-link{font-weight:400;color:#3176d9;background-color:transparent}.btn-link:hover{color:#1e53a0;text-decoration:none;background-color:transparent;border-color:transparent}.btn-link:focus,.btn-link.focus{text-decoration:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link:disabled,.btn-link.disabled{color:#888;pointer-events:none}.btn-lg,.btn-group-lg>.btn{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-sm,.btn-group-sm>.btn{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}@media screen and (prefers-reduced-motion:reduce){.fade{-webkit-transition:none;-o-transition:none;transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}@media screen and (prefers-reduced-motion:reduce){.collapsing{-webkit-transition:none;-o-transition:none;transition:none}}.dropup,.dropright,.dropdown,.dropleft{position:relative}.dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#222;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;-webkit-box-shadow:0 .5rem 1rem rgba(0,0,0,.175);box-shadow:0 .5rem 1rem rgba(0,0,0,.175)}.dropdown-menu-right{right:0;left:auto}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;width:0;height:0;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=top],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #eee}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#222;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:hover,.dropdown-item:focus{color:#151515;text-decoration:none;background:#f8f9fa -webkit-gradient(linear,left top,left bottom,from(#f9fafb),to(#f8f9fa)) repeat-x;background:#f8f9fa -webkit-linear-gradient(top,#f9fafb,#f8f9fa) repeat-x;background:#f8f9fa -o-linear-gradient(top,#f9fafb,#f8f9fa) repeat-x;background:#f8f9fa linear-gradient(180deg,#f9fafb,#f8f9fa) repeat-x}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x}.dropdown-item.disabled,.dropdown-item:disabled{color:#888;background-color:transparent;background-image:none}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#888;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#222}.btn-group,.btn-group-vertical{position:relative;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover{z-index:1}.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn.active{z-index:1}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group,.btn-group-vertical .btn+.btn,.btn-group-vertical .btn+.btn-group,.btn-group-vertical .btn-group+.btn,.btn-group-vertical .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:not(:last-child):not(.dropdown-toggle),.btn-group>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:not(:first-child),.btn-group>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-lg+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group.show .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.show .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn-group-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.btn-group-vertical .btn,.btn-group-vertical .btn-group{width:100%}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle),.btn-group-vertical>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.custom-select,.input-group>.custom-file{position:relative;-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;margin-bottom:0}.input-group>.form-control+.form-control,.input-group>.form-control+.custom-select,.input-group>.form-control+.custom-file,.input-group>.custom-select+.form-control,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.custom-file,.input-group>.custom-file+.form-control,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.custom-file{margin-left:-1px}.input-group>.form-control:focus,.input-group>.custom-select:focus,.input-group>.custom-file .custom-file-input:focus~.custom-file-label{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.form-control:not(:last-child),.input-group>.custom-select:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.form-control:not(:first-child),.input-group>.custom-select:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-prepend,.input-group-append{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.input-group-prepend .btn,.input-group-append .btn{position:relative;z-index:2}.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.input-group-text,.input-group-append .input-group-text+.btn{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#eee;border:1px solid #ccc;border-radius:.25rem}.input-group-text input[type=radio],.input-group-text input[type=checkbox]{margin-top:0}.input-group-lg>.form-control,.input-group-lg>.input-group-prepend>.input-group-text,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-append>.btn{height:-webkit-calc(2.875rem + 2px);height:calc(2.875rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.form-control,.input-group-sm>.input-group-prepend>.input-group-text,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-append>.btn{height:-webkit-calc(1.8125rem + 2px);height:calc(1.8125rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text,.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;z-index:-1;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x;-webkit-box-shadow:none;box-shadow:none}.custom-control-input:focus~.custom-control-label::before{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(48,99,142,.25);box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(48,99,142,.25)}.custom-control-input:active~.custom-control-label::before{color:#fff;background-color:#95bbdb;-webkit-box-shadow:none;box-shadow:none}.custom-control-input:disabled~.custom-control-label{color:#888}.custom-control-input:disabled~.custom-control-label::before{background-color:#eee}.custom-control-label{position:relative;margin-bottom:0}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#dee2e6;-webkit-box-shadow:inset 0 .25rem .25rem rgba(0,0,0,.1);box-shadow:inset 0 .25rem .25rem rgba(0,0,0,.1)}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background-repeat:no-repeat;background-position:50%;-webkit-background-size:50% 50%;background-size:50% 50%}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::before{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA4IDgiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik02LjU2NC43NWwtMy41OSAzLjYxMi0xLjUzOC0xLjU1TDAgNC4yNiAyLjk3NCA3LjI1IDggMi4xOTN6Ii8+PC9zdmc+)}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x;-webkit-box-shadow:none;box-shadow:none}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0IDQiPjxwYXRoIHN0cm9rZT0iI2ZmZiIgZD0iTTAgMmg0Ii8+PC9zdmc+)}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(48,99,142,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(48,99,142,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::before{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii00IC00IDggOCI+PGNpcmNsZSByPSIzIiBmaWxsPSIjZmZmIi8+PC9zdmc+)}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(48,99,142,.5)}.custom-select{display:inline-block;width:100%;height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px);padding:.375rem 1.75rem .375rem .75rem;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0IDUiPjxwYXRoIGZpbGw9IiMzMzMiIGQ9Ik0yIDAgMCAyaDR6bTAgNUwwIDNoNHoiLz48L3N2Zz4=) no-repeat 100% .75rem 50%;-webkit-background-size:8px 10px;background-size:8px 10px;border:1px solid #ccc;border-radius:.25rem;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.075);box-shadow:inset 0 1px 2px rgba(0,0,0,.075);-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#6fa3ce;outline:0;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.075),0 0 0 .2rem rgba(111,163,206,.5);box-shadow:inset 0 1px 2px rgba(0,0,0,.075),0 0 0 .2rem rgba(111,163,206,.5)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#888;background-color:#eee}.custom-select::-ms-expand{opacity:0}.custom-select-sm{height:-webkit-calc(1.8125rem + 2px);height:calc(1.8125rem + 2px);padding-top:.375rem;padding-bottom:.375rem;font-size:75%}.custom-select-lg{height:-webkit-calc(2.875rem + 2px);height:calc(2.875rem + 2px);padding-top:.375rem;padding-bottom:.375rem;font-size:125%}.custom-file{position:relative;display:inline-block;width:100%;height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px);margin:0;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#6fa3ce;-webkit-box-shadow:0 0 0 .2rem rgba(48,99,142,.25);box-shadow:0 0 0 .2rem rgba(48,99,142,.25)}.custom-file-input:focus~.custom-file-label::after{border-color:#6fa3ce}.custom-file-input:disabled~.custom-file-label{background-color:#eee}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px);padding:.375rem .75rem;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ccc;border-radius:.25rem;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:2.25rem;padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background:#eee -webkit-gradient(linear,left top,left bottom,from(#f1f1f1),to(#eee)) repeat-x;background:#eee -webkit-linear-gradient(top,#f1f1f1,#eee) repeat-x;background:#eee -o-linear-gradient(top,#f1f1f1,#eee) repeat-x;background:#eee linear-gradient(180deg,#f1f1f1,#eee) repeat-x;border-left:1px solid #ccc;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;padding-left:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:none}.custom-range:focus::-webkit-slider-thumb{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(48,99,142,.25);box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(48,99,142,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(48,99,142,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(48,99,142,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x;border:0;border-radius:1rem;-webkit-box-shadow:0 .1rem .25rem rgba(0,0,0,.1);box-shadow:0 .1rem .25rem rgba(0,0,0,.1);-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media screen and (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;-o-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background:#95bbdb -webkit-gradient(linear,left top,left bottom,from(#a5c5e1),to(#95bbdb)) repeat-x;background:#95bbdb -webkit-linear-gradient(top,#a5c5e1,#95bbdb) repeat-x;background:#95bbdb linear-gradient(180deg,#a5c5e1,#95bbdb) repeat-x}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem;-webkit-box-shadow:inset 0 .25rem .25rem rgba(0,0,0,.1);box-shadow:inset 0 .25rem .25rem rgba(0,0,0,.1)}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x;border:0;border-radius:1rem;box-shadow:0 .1rem .25rem rgba(0,0,0,.1);-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media screen and (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-webkit-transition:none;-o-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background:#95bbdb linear-gradient(180deg,#a5c5e1,#95bbdb) repeat-x}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem;box-shadow:inset 0 .25rem .25rem rgba(0,0,0,.1)}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x;border:0;border-radius:1rem;box-shadow:0 .1rem .25rem rgba(0,0,0,.1);-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;appearance:none}@media screen and (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-webkit-transition:none;-o-transition:none;transition:none}}.custom-range::-ms-thumb:active{background:#95bbdb linear-gradient(180deg,#a5c5e1,#95bbdb) repeat-x}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem;box-shadow:inset 0 .25rem .25rem rgba(0,0,0,.1)}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-control-label::before,.custom-file-label,.custom-select{-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media screen and (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{-webkit-transition:none;-o-transition:none;transition:none}}.nav{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:hover,.nav-link:focus{text-decoration:none}.nav-link.disabled{color:#888}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:hover,.nav-tabs .nav-link:focus{border-color:#eee #eee #dee2e6}.nav-tabs .nav-link.disabled{color:#888;background-color:transparent;border-color:transparent}.nav-tabs .nav-link.active,.nav-tabs .nav-item.show .nav-link{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#30638e}.nav-fill .nav-item{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar>.container,.navbar>.container-fluid{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-nav{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-webkit-flex-basis:100%;-ms-flex-preferred-size:100%;flex-basis:100%;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:hover,.navbar-toggler:focus{text-decoration:none}.navbar-toggler:not(:disabled):not(.disabled){cursor:pointer}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat 50%;-webkit-background-size:100% 100%;background-size:100% 100%}@media(max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{padding-right:0;padding-left:0}}@media(min-width:576px){.navbar-expand-sm{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media(max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{padding-right:0;padding-left:0}}@media(min-width:768px){.navbar-expand-md{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media(max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{padding-right:0;padding-left:0}}@media(min-width:992px){.navbar-expand-lg{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media(max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{padding-right:0;padding-left:0}}@media(min-width:1200px){.navbar-expand-xl{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:hover,.navbar-light .navbar-brand:focus{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:hover,.navbar-light .navbar-nav .nav-link:focus{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .show>.nav-link,.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .nav-link.active{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMzAgMzAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggc3Ryb2tlPSJyZ2JhKDAsIDAsIDAsIDAuNSkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIGQ9Ik00IDdoMjJNNCAxNWgyMk00IDIzaDIyIi8+PC9zdmc+)}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:hover,.navbar-light .navbar-text a:focus{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:hover,.navbar-dark .navbar-brand:focus{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link:hover,.navbar-dark .navbar-nav .nav-link:focus{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .show>.nav-link,.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .nav-link.active{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.75);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMzAgMzAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggc3Ryb2tlPSJyZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNzUpIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBkPSJNNCA3aDIyTTQgMTVoMjJNNCAyM2gyMiIvPjwvc3ZnPg==)}.navbar-dark .navbar-text{color:rgba(255,255,255,.75)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:hover,.navbar-dark .navbar-text a:focus{color:#fff}.card,.td-content .highlight{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr,.td-content .highlight>hr{margin-right:0;margin-left:0}.card>.list-group:first-child .list-group-item:first-child,.td-content .highlight>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child,.td-content .highlight>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-body{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:-webkit-calc(0.25rem - 1px) -webkit-calc(0.25rem - 1px) 0 0;border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 -webkit-calc(0.25rem - 1px) -webkit-calc(0.25rem - 1px);border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img{width:100%;border-radius:-webkit-calc(0.25rem - 1px);border-radius:calc(0.25rem - 1px)}.card-img-top{width:100%;border-top-left-radius:-webkit-calc(0.25rem - 1px);border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:-webkit-calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.card-img-bottom{width:100%;border-bottom-right-radius:-webkit-calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px);border-bottom-left-radius:-webkit-calc(0.25rem - 1px);border-bottom-left-radius:calc(0.25rem - 1px)}.card-deck{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.card-deck .card,.card-deck .td-content .highlight,.td-content .card-deck .highlight{margin-bottom:15px}@media(min-width:576px){.card-deck{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card,.card-deck .td-content .highlight,.td-content .card-deck .highlight{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1 0 0%;-ms-flex:1 0 0%;flex:1 0 0%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.card-group>.card,.td-content .card-group>.highlight{margin-bottom:15px}@media(min-width:576px){.card-group{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card,.td-content .card-group>.highlight{-webkit-box-flex:1;-webkit-flex:1 0 0%;-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card,.td-content .card-group>.highlight+.card,.td-content .card-group>.card+.highlight,.td-content .card-group>.highlight+.highlight{margin-left:0;border-left:0}.card-group>.card:first-child,.td-content .card-group>.highlight:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:first-child .card-img-top,.td-content .card-group>.highlight:first-child .card-img-top,.card-group>.card:first-child .card-header,.td-content .card-group>.highlight:first-child .card-header{border-top-right-radius:0}.card-group>.card:first-child .card-img-bottom,.td-content .card-group>.highlight:first-child .card-img-bottom,.card-group>.card:first-child .card-footer,.td-content .card-group>.highlight:first-child .card-footer{border-bottom-right-radius:0}.card-group>.card:last-child,.td-content .card-group>.highlight:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:last-child .card-img-top,.td-content .card-group>.highlight:last-child .card-img-top,.card-group>.card:last-child .card-header,.td-content .card-group>.highlight:last-child .card-header{border-top-left-radius:0}.card-group>.card:last-child .card-img-bottom,.td-content .card-group>.highlight:last-child .card-img-bottom,.card-group>.card:last-child .card-footer,.td-content .card-group>.highlight:last-child .card-footer{border-bottom-left-radius:0}.card-group>.card:only-child,.td-content .card-group>.highlight:only-child{border-radius:.25rem}.card-group>.card:only-child .card-img-top,.td-content .card-group>.highlight:only-child .card-img-top,.card-group>.card:only-child .card-header,.td-content .card-group>.highlight:only-child .card-header{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-group>.card:only-child .card-img-bottom,.td-content .card-group>.highlight:only-child .card-img-bottom,.card-group>.card:only-child .card-footer,.td-content .card-group>.highlight:only-child .card-footer{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-group>.card:not(:first-child):not(:last-child):not(:only-child),.td-content .card-group>.highlight:not(:first-child):not(:last-child):not(:only-child){border-radius:0}.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-img-top,.td-content .card-group>.highlight:not(:first-child):not(:last-child):not(:only-child) .card-img-top,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom,.td-content .card-group>.highlight:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-header,.td-content .card-group>.highlight:not(:first-child):not(:last-child):not(:only-child) .card-header,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-footer,.td-content .card-group>.highlight:not(:first-child):not(:last-child):not(:only-child) .card-footer{border-radius:0}}.card-columns .card,.card-columns .td-content .highlight,.td-content .card-columns .highlight{margin-bottom:.75rem}@media(min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card,.card-columns .td-content .highlight,.td-content .card-columns .highlight{display:inline-block;width:100%}}.accordion .card:not(:first-of-type):not(:last-of-type),.accordion .td-content .highlight:not(:first-of-type):not(:last-of-type),.td-content .accordion .highlight:not(:first-of-type):not(:last-of-type){border-bottom:0;border-radius:0}.accordion .card:not(:first-of-type) .card-header:first-child,.accordion .td-content .highlight:not(:first-of-type) .card-header:first-child,.td-content .accordion .highlight:not(:first-of-type) .card-header:first-child{border-radius:0}.accordion .card:first-of-type,.accordion .td-content .highlight:first-of-type,.td-content .accordion .highlight:first-of-type{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion .card:last-of-type,.accordion .td-content .highlight:last-of-type,.td-content .accordion .highlight:last-of-type{border-top-left-radius:0;border-top-right-radius:0}.breadcrumb{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#eee;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;color:#888;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#888}.pagination{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#888;background-color:#fff;border:1px solid rgba(0,0,0,.1)}.page-link:hover{z-index:2;color:#1e53a0;text-decoration:none;background-color:#eee;border-color:#dee2e6}.page-link:focus{z-index:2;outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(48,99,142,.25);box-shadow:0 0 0 .2rem rgba(48,99,142,.25)}.page-link:not(:disabled):not(.disabled){cursor:pointer}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:1;color:#fff;background-color:#30638e;border-color:#2a567b}.page-item.disabled .page-link{color:#dee2e6;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#30638e}.badge-primary[href]:hover,.badge-primary[href]:focus{color:#fff;text-decoration:none;background-color:#234868}.badge-secondary{color:#fff;background-color:#ffa630}.badge-secondary[href]:hover,.badge-secondary[href]:focus{color:#fff;text-decoration:none;background-color:#fc9000}.badge-success{color:#fff;background-color:#3772ff}.badge-success[href]:hover,.badge-success[href]:focus{color:#fff;text-decoration:none;background-color:#044eff}.badge-info{color:#222;background-color:#c0e0de}.badge-info[href]:hover,.badge-info[href]:focus{color:#222;text-decoration:none;background-color:#9ecfcc}.badge-warning{color:#fff;background-color:#ed6a5a}.badge-warning[href]:hover,.badge-warning[href]:focus{color:#fff;text-decoration:none;background-color:#e8402c}.badge-danger{color:#fff;background-color:#ed6a5a}.badge-danger[href]:hover,.badge-danger[href]:focus{color:#fff;text-decoration:none;background-color:#e8402c}.badge-light{color:#222;background-color:#d3f3ee}.badge-light[href]:hover,.badge-light[href]:focus{color:#222;text-decoration:none;background-color:#abe8df}.badge-dark{color:#fff;background-color:#403f4c}.badge-dark[href]:hover,.badge-dark[href]:focus{color:#fff;text-decoration:none;background-color:#292830}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#eee;border-radius:.3rem}@media(min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#19334a;background:#d6e0e8 -webkit-gradient(linear,left top,left bottom,from(#dce5eb),to(#d6e0e8)) repeat-x;background:#d6e0e8 -webkit-linear-gradient(top,#dce5eb,#d6e0e8) repeat-x;background:#d6e0e8 -o-linear-gradient(top,#dce5eb,#d6e0e8) repeat-x;background:#d6e0e8 linear-gradient(180deg,#dce5eb,#d6e0e8) repeat-x;border-color:#c5d3df}.alert-primary hr{border-top-color:#b5c7d6}.alert-primary .alert-link{color:#0c1924}.alert-secondary{color:#855619;background:#ffedd6 -webkit-gradient(linear,left top,left bottom,from(#fff0dc),to(#ffedd6)) repeat-x;background:#ffedd6 -webkit-linear-gradient(top,#fff0dc,#ffedd6) repeat-x;background:#ffedd6 -o-linear-gradient(top,#fff0dc,#ffedd6) repeat-x;background:#ffedd6 linear-gradient(180deg,#fff0dc,#ffedd6) repeat-x;border-color:#ffe6c5}.alert-secondary hr{border-top-color:#ffdbac}.alert-secondary .alert-link{color:#5a3a11}.alert-success{color:#1d3b85;background:#d7e3ff -webkit-gradient(linear,left top,left bottom,from(#dde7ff),to(#d7e3ff)) repeat-x;background:#d7e3ff -webkit-linear-gradient(top,#dde7ff,#d7e3ff) repeat-x;background:#d7e3ff -o-linear-gradient(top,#dde7ff,#d7e3ff) repeat-x;background:#d7e3ff linear-gradient(180deg,#dde7ff,#d7e3ff) repeat-x;border-color:#c7d8ff}.alert-success hr{border-top-color:#aec6ff}.alert-success .alert-link{color:#14285b}.alert-info{color:#647473;background:#f2f9f8 -webkit-gradient(linear,left top,left bottom,from(#f4faf9),to(#f2f9f8)) repeat-x;background:#f2f9f8 -webkit-linear-gradient(top,#f4faf9,#f2f9f8) repeat-x;background:#f2f9f8 -o-linear-gradient(top,#f4faf9,#f2f9f8) repeat-x;background:#f2f9f8 linear-gradient(180deg,#f4faf9,#f2f9f8) repeat-x;border-color:#edf6f6}.alert-info hr{border-top-color:#dceeee}.alert-info .alert-link{color:#4c5958}.alert-warning{color:#7b372f;background:#fbe1de -webkit-gradient(linear,left top,left bottom,from(#fce6e3),to(#fbe1de)) repeat-x;background:#fbe1de -webkit-linear-gradient(top,#fce6e3,#fbe1de) repeat-x;background:#fbe1de -o-linear-gradient(top,#fce6e3,#fbe1de) repeat-x;background:#fbe1de linear-gradient(180deg,#fce6e3,#fbe1de) repeat-x;border-color:#fad5d1}.alert-warning hr{border-top-color:#f8c0ba}.alert-warning .alert-link{color:#562721}.alert-danger{color:#7b372f;background:#fbe1de -webkit-gradient(linear,left top,left bottom,from(#fce6e3),to(#fbe1de)) repeat-x;background:#fbe1de -webkit-linear-gradient(top,#fce6e3,#fbe1de) repeat-x;background:#fbe1de -o-linear-gradient(top,#fce6e3,#fbe1de) repeat-x;background:#fbe1de linear-gradient(180deg,#fce6e3,#fbe1de) repeat-x;border-color:#fad5d1}.alert-danger hr{border-top-color:#f8c0ba}.alert-danger .alert-link{color:#562721}.alert-light{color:#6e7e7c;background:#f6fdfc -webkit-gradient(linear,left top,left bottom,from(#f7fdfc),to(#f6fdfc)) repeat-x;background:#f6fdfc -webkit-linear-gradient(top,#f7fdfc,#f6fdfc) repeat-x;background:#f6fdfc -o-linear-gradient(top,#f7fdfc,#f6fdfc) repeat-x;background:#f6fdfc linear-gradient(180deg,#f7fdfc,#f6fdfc) repeat-x;border-color:#f3fcfa}.alert-light hr{border-top-color:#dff7f2}.alert-light .alert-link{color:#566361}.alert-dark{color:#212128;background:#d9d9db -webkit-gradient(linear,left top,left bottom,from(#dfdfe0),to(#d9d9db)) repeat-x;background:#d9d9db -webkit-linear-gradient(top,#dfdfe0,#d9d9db) repeat-x;background:#d9d9db -o-linear-gradient(top,#dfdfe0,#d9d9db) repeat-x;background:#d9d9db linear-gradient(180deg,#dfdfe0,#d9d9db) repeat-x;border-color:#cac9cd}.alert-dark hr{border-top-color:#bdbcc1}.alert-dark .alert-link{color:#0a0a0c}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#eee;border-radius:.25rem;-webkit-box-shadow:inset 0 .1rem .1rem rgba(0,0,0,.1);box-shadow:inset 0 .1rem .1rem rgba(0,0,0,.1)}.progress-bar{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;color:#fff;text-align:center;white-space:nowrap;background-color:#30638e;-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}@media screen and (prefers-reduced-motion:reduce){.progress-bar{-webkit-transition:none;-o-transition:none;transition:none}}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:1rem 1rem;background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;-o-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}.media{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start}.media-body{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.list-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:hover,.list-group-item-action:focus{color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#222;background-color:#eee}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;margin-bottom:-1px;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item:hover,.list-group-item:focus{z-index:1;text-decoration:none}.list-group-item.disabled,.list-group-item:disabled{color:#888;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#30638e;border-color:#30638e}.list-group-flush .list-group-item{border-right:0;border-left:0;border-radius:0}.list-group-flush:first-child .list-group-item:first-child{border-top:0}.list-group-flush:last-child .list-group-item:last-child{border-bottom:0}.list-group-item-primary{color:#19334a;background-color:#c5d3df}.list-group-item-primary.list-group-item-action:hover,.list-group-item-primary.list-group-item-action:focus{color:#19334a;background-color:#b5c7d6}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#19334a;border-color:#19334a}.list-group-item-secondary{color:#855619;background-color:#ffe6c5}.list-group-item-secondary.list-group-item-action:hover,.list-group-item-secondary.list-group-item-action:focus{color:#855619;background-color:#ffdbac}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#855619;border-color:#855619}.list-group-item-success{color:#1d3b85;background-color:#c7d8ff}.list-group-item-success.list-group-item-action:hover,.list-group-item-success.list-group-item-action:focus{color:#1d3b85;background-color:#aec6ff}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#1d3b85;border-color:#1d3b85}.list-group-item-info{color:#647473;background-color:#edf6f6}.list-group-item-info.list-group-item-action:hover,.list-group-item-info.list-group-item-action:focus{color:#647473;background-color:#dceeee}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#647473;border-color:#647473}.list-group-item-warning{color:#7b372f;background-color:#fad5d1}.list-group-item-warning.list-group-item-action:hover,.list-group-item-warning.list-group-item-action:focus{color:#7b372f;background-color:#f8c0ba}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#7b372f;border-color:#7b372f}.list-group-item-danger{color:#7b372f;background-color:#fad5d1}.list-group-item-danger.list-group-item-action:hover,.list-group-item-danger.list-group-item-action:focus{color:#7b372f;background-color:#f8c0ba}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#7b372f;border-color:#7b372f}.list-group-item-light{color:#6e7e7c;background-color:#f3fcfa}.list-group-item-light.list-group-item-action:hover,.list-group-item-light.list-group-item-action:focus{color:#6e7e7c;background-color:#dff7f2}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#6e7e7c;border-color:#6e7e7c}.list-group-item-dark{color:#212128;background-color:#cac9cd}.list-group-item-dark.list-group-item-action:hover,.list-group-item-dark.list-group-item-action:focus{color:#212128;background-color:#bdbcc1}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#212128;border-color:#212128}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:not(:disabled):not(.disabled){cursor:pointer}.close:not(:disabled):not(.disabled):hover,.close:not(:disabled):not(.disabled):focus{color:#000;text-decoration:none;opacity:.75}button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out,-o-transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}@media screen and (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{-webkit-transition:none;-o-transition:none;transition:none}}.modal.show .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-dialog-centered{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;min-height:-webkit-calc(100% - (0.5rem * 2));min-height:calc(100% - (0.5rem * 2))}.modal-dialog-centered::before{display:block;height:-webkit-calc(100vh - (0.5rem * 2));height:calc(100vh - (0.5rem * 2));content:""}.modal-content{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;-webkit-box-shadow:0 .25rem .5rem rgba(0,0,0,.5);box-shadow:0 .25rem .5rem rgba(0,0,0,.5);outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;padding:1rem;border-bottom:1px solid #eee;border-top-left-radius:.3rem;border-top-right-radius:.3rem}.modal-header .close{padding:1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;padding:1rem;border-top:1px solid #eee}.modal-footer>:not(:first-child){margin-left:.25rem}.modal-footer>:not(:last-child){margin-right:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media(min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-centered{min-height:-webkit-calc(100% - (1.75rem * 2));min-height:calc(100% - (1.75rem * 2))}.modal-dialog-centered::before{height:-webkit-calc(100vh - (1.75rem * 2));height:calc(100vh - (1.75rem * 2))}.modal-content{-webkit-box-shadow:0 .5rem 1rem rgba(0,0,0,.5);box-shadow:0 .5rem 1rem rgba(0,0,0,.5)}.modal-sm{max-width:300px}}@media(min-width:992px){.modal-lg{max-width:800px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:open sans,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-top,.bs-tooltip-auto[x-placement^=top]{padding:.4rem 0}.bs-tooltip-top .arrow,.bs-tooltip-auto[x-placement^=top] .arrow{bottom:0}.bs-tooltip-top .arrow::before,.bs-tooltip-auto[x-placement^=top] .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-right,.bs-tooltip-auto[x-placement^=right]{padding:0 .4rem}.bs-tooltip-right .arrow,.bs-tooltip-auto[x-placement^=right] .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-right .arrow::before,.bs-tooltip-auto[x-placement^=right] .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-bottom,.bs-tooltip-auto[x-placement^=bottom]{padding:.4rem 0}.bs-tooltip-bottom .arrow,.bs-tooltip-auto[x-placement^=bottom] .arrow{top:0}.bs-tooltip-bottom .arrow::before,.bs-tooltip-auto[x-placement^=bottom] .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-left,.bs-tooltip-auto[x-placement^=left]{padding:0 .4rem}.bs-tooltip-left .arrow,.bs-tooltip-auto[x-placement^=left] .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-left .arrow::before,.bs-tooltip-auto[x-placement^=left] .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:open sans,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;-webkit-box-shadow:0 .25rem .5rem rgba(0,0,0,.2);box-shadow:0 .25rem .5rem rgba(0,0,0,.2)}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::before,.popover .arrow::after{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-top,.bs-popover-auto[x-placement^=top]{margin-bottom:.5rem}.bs-popover-top .arrow,.bs-popover-auto[x-placement^=top] .arrow{bottom:-webkit-calc((0.5rem + 1px) * -1);bottom:calc((0.5rem + 1px) * -1)}.bs-popover-top .arrow::before,.bs-popover-auto[x-placement^=top] .arrow::before,.bs-popover-top .arrow::after,.bs-popover-auto[x-placement^=top] .arrow::after{border-width:.5rem .5rem 0}.bs-popover-top .arrow::before,.bs-popover-auto[x-placement^=top] .arrow::before{bottom:0;border-top-color:rgba(0,0,0,.25)}.bs-popover-top .arrow::after,.bs-popover-auto[x-placement^=top] .arrow::after{bottom:1px;border-top-color:#fff}.bs-popover-right,.bs-popover-auto[x-placement^=right]{margin-left:.5rem}.bs-popover-right .arrow,.bs-popover-auto[x-placement^=right] .arrow{left:-webkit-calc((0.5rem + 1px) * -1);left:calc((0.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-right .arrow::before,.bs-popover-auto[x-placement^=right] .arrow::before,.bs-popover-right .arrow::after,.bs-popover-auto[x-placement^=right] .arrow::after{border-width:.5rem .5rem .5rem 0}.bs-popover-right .arrow::before,.bs-popover-auto[x-placement^=right] .arrow::before{left:0;border-right-color:rgba(0,0,0,.25)}.bs-popover-right .arrow::after,.bs-popover-auto[x-placement^=right] .arrow::after{left:1px;border-right-color:#fff}.bs-popover-bottom,.bs-popover-auto[x-placement^=bottom]{margin-top:.5rem}.bs-popover-bottom .arrow,.bs-popover-auto[x-placement^=bottom] .arrow{top:-webkit-calc((0.5rem + 1px) * -1);top:calc((0.5rem + 1px) * -1)}.bs-popover-bottom .arrow::before,.bs-popover-auto[x-placement^=bottom] .arrow::before,.bs-popover-bottom .arrow::after,.bs-popover-auto[x-placement^=bottom] .arrow::after{border-width:0 .5rem .5rem}.bs-popover-bottom .arrow::before,.bs-popover-auto[x-placement^=bottom] .arrow::before{top:0;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-bottom .arrow::after,.bs-popover-auto[x-placement^=bottom] .arrow::after{top:1px;border-bottom-color:#fff}.bs-popover-bottom .popover-header::before,.bs-popover-auto[x-placement^=bottom] .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-left,.bs-popover-auto[x-placement^=left]{margin-right:.5rem}.bs-popover-left .arrow,.bs-popover-auto[x-placement^=left] .arrow{right:-webkit-calc((0.5rem + 1px) * -1);right:calc((0.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-left .arrow::before,.bs-popover-auto[x-placement^=left] .arrow::before,.bs-popover-left .arrow::after,.bs-popover-auto[x-placement^=left] .arrow::after{border-width:.5rem 0 .5rem .5rem}.bs-popover-left .arrow::before,.bs-popover-auto[x-placement^=left] .arrow::before{right:0;border-left-color:rgba(0,0,0,.25)}.bs-popover-left .arrow::after,.bs-popover-auto[x-placement^=left] .arrow::after{right:1px;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;color:inherit;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:-webkit-calc(0.3rem - 1px);border-top-left-radius:calc(0.3rem - 1px);border-top-right-radius:-webkit-calc(0.3rem - 1px);border-top-right-radius:calc(0.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#222}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-item{position:relative;display:none;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;width:100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-item.active,.carousel-item-next,.carousel-item-prev{display:block;-webkit-transition:-webkit-transform .6s ease;transition:-webkit-transform .6s ease;-o-transition:-o-transform .6s ease;transition:transform .6s ease;transition:transform .6s ease,-webkit-transform .6s ease,-o-transform .6s ease}@media screen and (prefers-reduced-motion:reduce){.carousel-item.active,.carousel-item-next,.carousel-item-prev{-webkit-transition:none;-o-transition:none;transition:none}}.carousel-item-next,.carousel-item-prev{position:absolute;top:0}.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translateX(0);-ms-transform:translateX(0);-o-transform:translateX(0);transform:translateX(0)}@supports((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-item-next,.active.carousel-item-right{-webkit-transform:translateX(100%);-ms-transform:translateX(100%);-o-transform:translateX(100%);transform:translateX(100%)}@supports((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-item-next,.active.carousel-item-right{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.carousel-item-prev,.active.carousel-item-left{-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);-o-transform:translateX(-100%);transform:translateX(-100%)}@supports((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-item-prev,.active.carousel-item-left{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.carousel-fade .carousel-item{opacity:0;-webkit-transition-duration:.6s;-o-transition-duration:.6s;transition-duration:.6s;-webkit-transition-property:opacity;-o-transition-property:opacity;transition-property:opacity}.carousel-fade .carousel-item.active,.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right{opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{opacity:0}.carousel-fade .carousel-item-next,.carousel-fade .carousel-item-prev,.carousel-fade .carousel-item.active,.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-prev{-webkit-transform:translateX(0);-ms-transform:translateX(0);-o-transform:translateX(0);transform:translateX(0)}@supports((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-fade .carousel-item-next,.carousel-fade .carousel-item-prev,.carousel-fade .carousel-item.active,.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-prev{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-control-prev,.carousel-control-next{position:absolute;top:0;bottom:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0;background:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,0.25)),to(rgba(0,0,0,0.001)));background:-webkit-linear-gradient(left,rgba(0,0,0,0.25),rgba(0,0,0,0.001));background:-o-linear-gradient(left,rgba(0,0,0,0.25),rgba(0,0,0,0.001));background:linear-gradient(90deg,rgba(0,0,0,0.25),rgba(0,0,0,0.001))}.carousel-control-next{right:0;background:-webkit-gradient(linear,right top,left top,from(rgba(0,0,0,0.25)),to(rgba(0,0,0,0.001)));background:-webkit-linear-gradient(right,rgba(0,0,0,0.25),rgba(0,0,0,0.001));background:-o-linear-gradient(right,rgba(0,0,0,0.25),rgba(0,0,0,0.001));background:linear-gradient(270deg,rgba(0,0,0,0.25),rgba(0,0,0,0.001))}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:20px;height:20px;background:transparent no-repeat 50%;-webkit-background-size:100% 100%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiNmZmYiIHZpZXdCb3g9IjAgMCA4IDgiPjxwYXRoIGQ9Ik01LjI1LjBsLTQgNCA0IDQgMS41LTEuNUw0LjI1IDRsMi41LTIuNUw1LjI1LjB6Ii8+PC9zdmc+)}.carousel-control-next-icon{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiNmZmYiIHZpZXdCb3g9IjAgMCA4IDgiPjxwYXRoIGQ9Ik0yLjc1LjBsLTEuNSAxLjVMMy43NSA0bC0yLjUgMi41TDIuNzUgOGw0LTQtNC00eiIvPjwvc3ZnPg==)}.carousel-indicators{position:absolute;right:0;bottom:10px;left:0;z-index:15;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{position:relative;-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:rgba(255,255,255,.5)}.carousel-indicators li::before{position:absolute;top:-10px;left:0;display:inline-block;width:100%;height:10px;content:""}.carousel-indicators li::after{position:absolute;bottom:-10px;left:0;display:inline-block;width:100%;height:10px;content:""}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#30638e!important}a.bg-primary:hover,a.bg-primary:focus,button.bg-primary:hover,button.bg-primary:focus{background-color:#234868!important}.bg-secondary{background-color:#ffa630!important}a.bg-secondary:hover,a.bg-secondary:focus,button.bg-secondary:hover,button.bg-secondary:focus{background-color:#fc9000!important}.bg-success{background-color:#3772ff!important}a.bg-success:hover,a.bg-success:focus,button.bg-success:hover,button.bg-success:focus{background-color:#044eff!important}.bg-info{background-color:#c0e0de!important}a.bg-info:hover,a.bg-info:focus,button.bg-info:hover,button.bg-info:focus{background-color:#9ecfcc!important}.bg-warning{background-color:#ed6a5a!important}a.bg-warning:hover,a.bg-warning:focus,button.bg-warning:hover,button.bg-warning:focus{background-color:#e8402c!important}.bg-danger{background-color:#ed6a5a!important}a.bg-danger:hover,a.bg-danger:focus,button.bg-danger:hover,button.bg-danger:focus{background-color:#e8402c!important}.bg-light{background-color:#d3f3ee!important}a.bg-light:hover,a.bg-light:focus,button.bg-light:hover,button.bg-light:focus{background-color:#abe8df!important}.bg-dark{background-color:#403f4c!important}a.bg-dark:hover,a.bg-dark:focus,button.bg-dark:hover,button.bg-dark:focus{background-color:#292830!important}.bg-gradient-primary{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x!important;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x!important}.bg-gradient-secondary{background:#FFA630 -webkit-gradient(linear,left top,left bottom,from(#ffb34f),to(#FFA630)) repeat-x!important;background:#ffa630 -webkit-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 -o-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 linear-gradient(180deg,#ffb34f,#FFA630) repeat-x!important}.bg-gradient-success{background:#3772FF -webkit-gradient(linear,left top,left bottom,from(#5587ff),to(#3772FF)) repeat-x!important;background:#3772ff -webkit-linear-gradient(top,#5587ff,#3772FF) repeat-x!important;background:#3772ff -o-linear-gradient(top,#5587ff,#3772FF) repeat-x!important;background:#3772ff linear-gradient(180deg,#5587ff,#3772FF) repeat-x!important}.bg-gradient-info{background:#C0E0DE -webkit-gradient(linear,left top,left bottom,from(#c9e5e3),to(#C0E0DE)) repeat-x!important;background:#c0e0de -webkit-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de -o-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de linear-gradient(180deg,#c9e5e3,#C0E0DE) repeat-x!important}.bg-gradient-warning{background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x!important;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x!important}.bg-gradient-danger{background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x!important;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x!important}.bg-gradient-light{background:#D3F3EE -webkit-gradient(linear,left top,left bottom,from(#daf5f1),to(#D3F3EE)) repeat-x!important;background:#d3f3ee -webkit-linear-gradient(top,#daf5f1,#D3F3EE) repeat-x!important;background:#d3f3ee -o-linear-gradient(top,#daf5f1,#D3F3EE) repeat-x!important;background:#d3f3ee linear-gradient(180deg,#daf5f1,#D3F3EE) repeat-x!important}.bg-gradient-dark{background:#403F4C -webkit-gradient(linear,left top,left bottom,from(#5d5c67),to(#403F4C)) repeat-x!important;background:#403f4c -webkit-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c -o-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c linear-gradient(180deg,#5d5c67,#403F4C) repeat-x!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#30638e!important}.border-secondary{border-color:#ffa630!important}.border-success{border-color:#3772ff!important}.border-info{border-color:#c0e0de!important}.border-warning{border-color:#ed6a5a!important}.border-danger{border-color:#ed6a5a!important}.border-light{border-color:#d3f3ee!important}.border-dark{border-color:#403f4c!important}.border-white{border-color:#fff!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-circle{border-radius:50%!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}@media(min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media(min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media(min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media(min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.85714286%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}@media(min-width:576px){.flex-sm-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media(min-width:768px){.flex-md-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media(min-width:992px){.flex-lg-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media(min-width:1200px){.flex-xl-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media(min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media(min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media(min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media(min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{-webkit-box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important;box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{-webkit-box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important;box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{-webkit-box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important;box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{-webkit-box-shadow:none!important;box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media(min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media(min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media(min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media(min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,liberation mono,courier new,monospace}.text-justify{text-align:justify!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media(min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media(min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media(min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media(min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#30638e!important}a.text-primary:hover,a.text-primary:focus{color:#234868!important}.text-secondary{color:#ffa630!important}a.text-secondary:hover,a.text-secondary:focus{color:#fc9000!important}.text-success{color:#3772ff!important}a.text-success:hover,a.text-success:focus{color:#044eff!important}.text-info{color:#c0e0de!important}a.text-info:hover,a.text-info:focus{color:#9ecfcc!important}.text-warning{color:#ed6a5a!important}a.text-warning:hover,a.text-warning:focus{color:#e8402c!important}.text-danger{color:#ed6a5a!important}a.text-danger:hover,a.text-danger:focus{color:#e8402c!important}.text-light{color:#d3f3ee!important}a.text-light:hover,a.text-light:focus{color:#abe8df!important}.text-dark{color:#403f4c!important}a.text-dark:hover,a.text-dark:focus{color:#292830!important}.text-body{color:#222!important}.text-muted{color:#888!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,*::before,*::after{text-shadow:none!important;-webkit-box-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}pre,blockquote{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table,.td-box .row.section>table,.td-content>table{border-collapse:collapse!important}.table td,.td-box .row.section>table td,.td-content>table td,.table th,.td-box .row.section>table th,.td-content>table th{background-color:#fff!important}.table-bordered th,.table-bordered td{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark th,.table-dark td,.table-dark thead th,.table-dark tbody+tbody{border-color:#dee2e6}.table .thead-dark th,.td-box .row.section>table .thead-dark th,.td-content>table .thead-dark th{color:inherit;border-color:#dee2e6}}/*!* Font Awesome Free 5.10.1 by @fontawesome - https://fontawesome.com +* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)*/.fa,.fas,.far,.fal,.fad,.fab{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:solid .08em #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fas.fa-pull-left,.far.fa-pull-left,.fal.fa-pull-left,.fab.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fas.fa-pull-right,.far.fa-pull-right,.fal.fa-pull-right,.fab.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;-o-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);-o-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-o-keyframes fa-spin{0%{-o-transform:rotate(0deg);transform:rotate(0deg)}100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);-o-transform:rotate(360deg);transform:rotate(360deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);-o-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(-1,-1);-ms-transform:scale(-1,-1);-o-transform:scale(-1,-1);transform:scale(-1,-1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-flip-both{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adobe:before{content:"\f778"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-atlassian:before{content:"\f77b"}.fa-atom:before{content:"\f5d2"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-baby:before{content:"\f77c"}.fa-baby-carriage:before{content:"\f77d"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-bacon:before{content:"\f7e5"}.fa-balance-scale:before{content:"\f24e"}.fa-balance-scale-left:before{content:"\f515"}.fa-balance-scale-right:before{content:"\f516"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-battle-net:before{content:"\f835"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bible:before{content:"\f647"}.fa-bicycle:before{content:"\f206"}.fa-biking:before{content:"\f84a"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-biohazard:before{content:"\f780"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blind:before{content:"\f29d"}.fa-blog:before{content:"\f781"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-dead:before{content:"\f6b7"}.fa-book-medical:before{content:"\f7e6"}.fa-book-open:before{content:"\f518"}.fa-book-reader:before{content:"\f5da"}.fa-bookmark:before{content:"\f02e"}.fa-bootstrap:before{content:"\f836"}.fa-border-all:before{content:"\f84c"}.fa-border-none:before{content:"\f850"}.fa-border-style:before{content:"\f853"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-bread-slice:before{content:"\f7ec"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-buffer:before{content:"\f837"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-business-time:before{content:"\f64a"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-day:before{content:"\f783"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-calendar-week:before{content:"\f784"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-campground:before{content:"\f6bb"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-candy-cane:before{content:"\f786"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-car-alt:before{content:"\f5de"}.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-side:before{content:"\f5e4"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-carrot:before{content:"\f787"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cash-register:before{content:"\f788"}.fa-cat:before{content:"\f6be"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-centos:before{content:"\f789"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-charging-station:before{content:"\f5e7"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-cheese:before{content:"\f7ef"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-chromecast:before{content:"\f838"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-city:before{content:"\f64f"}.fa-clinic-medical:before{content:"\f7f2"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-medical:before{content:"\f7f5"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-compress-arrows-alt:before{content:"\f78c"}.fa-concierge-bell:before{content:"\f562"}.fa-confluence:before{content:"\f78d"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-cotton-bureau:before{content:"\f89e"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-credit-card:before{content:"\f09d"}.fa-critical-role:before{content:"\f6c9"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-crutch:before{content:"\f7f7"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-delicious:before{content:"\f1a5"}.fa-democrat:before{content:"\f747"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dharmachakra:before{content:"\f655"}.fa-dhl:before{content:"\f790"}.fa-diagnoses:before{content:"\f470"}.fa-diaspora:before{content:"\f791"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-directions:before{content:"\f5eb"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dumpster:before{content:"\f793"}.fa-dumpster-fire:before{content:"\f794"}.fa-dungeon:before{content:"\f6d9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edit:before{content:"\f044"}.fa-egg:before{content:"\f7fb"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-ethernet:before{content:"\f796"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-evernote:before{content:"\f839"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fan:before{content:"\f863"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-fedex:before{content:"\f797"}.fa-fedora:before{content:"\f798"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-figma:before{content:"\f799"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-alt:before{content:"\f7e4"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-fist-raised:before{content:"\f6de"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-funnel-dollar:before{content:"\f662"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-gifts:before{content:"\f79c"}.fa-git:before{content:"\f1d3"}.fa-git-alt:before{content:"\f841"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-cheers:before{content:"\f79f"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glass-whiskey:before{content:"\f7a0"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-globe-europe:before{content:"\f7a2"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-lines:before{content:"\f7a4"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-guitar:before{content:"\f7a6"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hamburger:before{content:"\f805"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-middle-finger:before{content:"\f806"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-handshake:before{content:"\f2b5"}.fa-hanukiah:before{content:"\f6e6"}.fa-hard-hat:before{content:"\f807"}.fa-hashtag:before{content:"\f292"}.fa-hat-wizard:before{content:"\f6e8"}.fa-haykal:before{content:"\f666"}.fa-hdd:before{content:"\f0a0"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heart-broken:before{content:"\f7a9"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hiking:before{content:"\f6ec"}.fa-hippo:before{content:"\f6ed"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hockey-puck:before{content:"\f453"}.fa-holly-berry:before{content:"\f7aa"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-horse:before{content:"\f6f0"}.fa-horse-head:before{content:"\f7ab"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hot-tub:before{content:"\f593"}.fa-hotdog:before{content:"\f80f"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-house-damage:before{content:"\f6f1"}.fa-houzz:before{content:"\f27c"}.fa-hryvnia:before{content:"\f6f2"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-ice-cream:before{content:"\f810"}.fa-icicles:before{content:"\f7ad"}.fa-icons:before{content:"\f86d"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-igloo:before{content:"\f7ae"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-instagram:before{content:"\f16d"}.fa-intercom:before{content:"\f7af"}.fa-internet-explorer:before{content:"\f26b"}.fa-invision:before{content:"\f7b0"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itch-io:before{content:"\f83a"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi:before{content:"\f669"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-jira:before{content:"\f7b1"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-journal-whills:before{content:"\f66a"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaaba:before{content:"\f66b"}.fa-kaggle:before{content:"\f5fa"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-khanda:before{content:"\f66d"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laptop-medical:before{content:"\f812"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mail-bulk:before{content:"\f674"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-markdown:before{content:"\f60f"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mask:before{content:"\f6fa"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-mendeley:before{content:"\f7b3"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-meteor:before{content:"\f753"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mitten:before{content:"\f7b5"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mouse-pointer:before{content:"\f245"}.fa-mug-hot:before{content:"\f7b6"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-oil-can:before{content:"\f613"}.fa-old-republic:before{content:"\f510"}.fa-om:before{content:"\f679"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-osi:before{content:"\f41a"}.fa-otter:before{content:"\f700"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-pager:before{content:"\f815"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-pastafarianism:before{content:"\f67b"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-penny-arcade:before{content:"\f704"}.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-person-booth:before{content:"\f756"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-alt:before{content:"\f879"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-square-alt:before{content:"\f87b"}.fa-phone-volume:before{content:"\f2a0"}.fa-photo-video:before{content:"\f87c"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-pizza-slice:before{content:"\f818"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poll:before{content:"\f681"}.fa-poll-h:before{content:"\f682"}.fa-poo:before{content:"\f2fe"}.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-pray:before{content:"\f683"}.fa-praying-hands:before{content:"\f684"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-quran:before{content:"\f687"}.fa-r-project:before{content:"\f4f7"}.fa-radiation:before{content:"\f7b9"}.fa-radiation-alt:before{content:"\f7ba"}.fa-rainbow:before{content:"\f75b"}.fa-random:before{content:"\f074"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redhat:before{content:"\f7bc"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-remove-format:before{content:"\f87d"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-republican:before{content:"\f75e"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-restroom:before{content:"\f7bd"}.fa-retweet:before{content:"\f079"}.fa-rev:before{content:"\f5b2"}.fa-ribbon:before{content:"\f4d6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-route:before{content:"\f4d7"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-running:before{content:"\f70c"}.fa-rupee-sign:before{content:"\f156"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-salesforce:before{content:"\f83b"}.fa-sass:before{content:"\f41e"}.fa-satellite:before{content:"\f7bf"}.fa-satellite-dish:before{content:"\f7c0"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-scroll:before{content:"\f70e"}.fa-sd-card:before{content:"\f7c2"}.fa-search:before{content:"\f002"}.fa-search-dollar:before{content:"\f688"}.fa-search-location:before{content:"\f689"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-shapes:before{content:"\f61f"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-sim-card:before{content:"\f7c4"}.fa-simplybuilt:before{content:"\f215"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skating:before{content:"\f7c5"}.fa-sketch:before{content:"\f7c6"}.fa-skiing:before{content:"\f7c9"}.fa-skiing-nordic:before{content:"\f7ca"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-slash:before{content:"\f715"}.fa-sleigh:before{content:"\f7cc"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-sms:before{content:"\f7cd"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowboarding:before{content:"\f7ce"}.fa-snowflake:before{content:"\f2dc"}.fa-snowman:before{content:"\f7d0"}.fa-snowplow:before{content:"\f7d2"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-down-alt:before{content:"\f884"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-amount-up-alt:before{content:"\f885"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-sourcetree:before{content:"\f7d3"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-speaker-deck:before{content:"\f83c"}.fa-spell-check:before{content:"\f891"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-square-root-alt:before{content:"\f698"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stackpath:before{content:"\f842"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-suse:before{content:"\f7d6"}.fa-swatchbook:before{content:"\f5c3"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-symfony:before{content:"\f83d"}.fa-synagogue:before{content:"\f69b"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-tenge:before{content:"\f7d7"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-the-red-yeti:before{content:"\f69d"}.fa-theater-masks:before{content:"\f630"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-think-peaks:before{content:"\f731"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet:before{content:"\f7d8"}.fa-toilet-paper:before{content:"\f71e"}.fa-toolbox:before{content:"\f552"}.fa-tools:before{content:"\f7d9"}.fa-tooth:before{content:"\f5c9"}.fa-torah:before{content:"\f6a0"}.fa-torii-gate:before{content:"\f6a1"}.fa-tractor:before{content:"\f722"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-train:before{content:"\f238"}.fa-tram:before{content:"\f7da"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-trash-restore:before{content:"\f829"}.fa-trash-restore-alt:before{content:"\f82a"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-tripadvisor:before{content:"\f262"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-ubuntu:before{content:"\f7df"}.fa-uikit:before{content:"\f403"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-ups:before{content:"\f7e0"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-injured:before{content:"\f728"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-nurse:before{content:"\f82f"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-usps:before{content:"\f7e1"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-voicemail:before{content:"\f897"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-mute:before{content:"\f6a9"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vote-yea:before{content:"\f772"}.fa-vr-cardboard:before{content:"\f729"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-water:before{content:"\f773"}.fa-wave-square:before{content:"\f83e"}.fa-waze:before{content:"\f83f"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-wind:before{content:"\f72e"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yammer:before{content:"\f840"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yarn:before{content:"\f7e3"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}/*!* Font Awesome Free 5.10.1 by @fontawesome - https://fontawesome.com +* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)*/@font-face{font-family:'font awesome 5 free';font-style:normal;font-weight:900;font-display:auto;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.fas{font-family:'font awesome 5 free';font-weight:900}/*!* Font Awesome Free 5.10.1 by @fontawesome - https://fontawesome.com +* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)*/@font-face{font-family:'font awesome 5 brands';font-style:normal;font-weight:400;font-display:auto;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:'font awesome 5 brands'}.td-border-top{border:none;border-top:1px solid #eee}.td-border-none{border:none}.td-block-padding,.td-default main section{padding-top:4rem;padding-bottom:4rem}@media(min-width:768px){.td-block-padding,.td-default main section{padding-top:5rem;padding-bottom:5rem}}.td-overlay{position:relative}.td-overlay::after{content:"";position:absolute;top:0;right:0;bottom:0;left:0}.td-overlay--dark::after{background-color:rgba(64,63,76,.3)}.td-overlay--light::after{background-color:rgba(211,243,238,.3)}.td-overlay__inner{position:relative;z-index:1}@media(min-width:992px){.td-max-width-on-larger-screens,.td-content>pre,.td-content>.highlight,.td-content>.lead,.td-content>h1,.td-content>h2,.td-content>ul,.td-content>ol,.td-content>p,.td-content>blockquote,.td-content>dl dd,.td-content .footnotes,.td-content>.alert{max-width:80%}}.td-box--height-min{min-height:300px}.td-box--height-med{min-height:400px}.td-box--height-max{min-height:500px}.td-box--height-full{min-height:100vh}@media(min-width:768px){.td-box--height-min{min-height:450px}.td-box--height-med{min-height:500px}.td-box--height-max{min-height:650px}}.td-box .row.section{padding-left:5rem;padding-right:5rem;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.td-box .row{padding-left:5rem;padding-right:5rem;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.td-box.linkbox{padding:5rem}.td-box--0{color:#fff;background-color:#403f4c}.td-box--0 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#403f4c transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--0 p>a{color:#d9e5f8}.td-box--10.td-box--gradient{background:#403F4C -webkit-gradient(linear,left top,left bottom,from(#5d5c67),to(#403F4C)) repeat-x!important;background:#403f4c -webkit-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c -o-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c linear-gradient(180deg,#5d5c67,#403F4C) repeat-x!important}.td-box--1{color:#fff;background-color:#30638e}.td-box--1 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#30638e transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--1 p>a{color:#cadcf5}.td-box--11.td-box--gradient{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x!important;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x!important}.td-box--2{color:#fff;background-color:#ffa630}.td-box--2 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ffa630 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--2 p>a{color:#abc7f0}.td-box--12.td-box--gradient{background:#FFA630 -webkit-gradient(linear,left top,left bottom,from(#ffb34f),to(#FFA630)) repeat-x!important;background:#ffa630 -webkit-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 -o-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 linear-gradient(180deg,#ffb34f,#FFA630) repeat-x!important}.td-box--3{color:#222;background-color:#c0e0de}.td-box--3 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#c0e0de transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--3 p>a{color:#638ac1}.td-box--13.td-box--gradient{background:#C0E0DE -webkit-gradient(linear,left top,left bottom,from(#c9e5e3),to(#C0E0DE)) repeat-x!important;background:#c0e0de -webkit-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de -o-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de linear-gradient(180deg,#c9e5e3,#C0E0DE) repeat-x!important}.td-box--4{color:#222;background-color:#fff}.td-box--4 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#fff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--4 p>a{color:#72a1e5}.td-box--14.td-box--gradient{background:white -webkit-gradient(linear,left top,left bottom,from(white),to(white)) repeat-x!important;background:#fff -webkit-linear-gradient(top,white,white) repeat-x!important;background:#fff -o-linear-gradient(top,white,white) repeat-x!important;background:#fff linear-gradient(180deg,white,white) repeat-x!important}.td-box--5{color:#fff;background-color:#888}.td-box--5 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#888 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--5 p>a{color:#b4cdf1}.td-box--15.td-box--gradient{background:#888 -webkit-gradient(linear,left top,left bottom,from(#9a9a9a),to(#888)) repeat-x!important;background:#888 -webkit-linear-gradient(top,#9a9a9a,#888) repeat-x!important;background:#888 -o-linear-gradient(top,#9a9a9a,#888) repeat-x!important;background:#888 linear-gradient(180deg,#9a9a9a,#888) repeat-x!important}.td-box--6{color:#fff;background-color:#3772ff}.td-box--6 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#3772ff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--6 p>a{color:#a9c6ef}.td-box--16.td-box--gradient{background:#3772FF -webkit-gradient(linear,left top,left bottom,from(#5587ff),to(#3772FF)) repeat-x!important;background:#3772ff -webkit-linear-gradient(top,#5587ff,#3772FF) repeat-x!important;background:#3772ff -o-linear-gradient(top,#5587ff,#3772FF) repeat-x!important;background:#3772ff linear-gradient(180deg,#5587ff,#3772FF) repeat-x!important}.td-box--7{color:#fff;background-color:#ed6a5a}.td-box--7 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ed6a5a transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--7 p>a{color:#a5c3ee}.td-box--17.td-box--gradient{background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x!important;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x!important}.td-box--8{color:#fff;background-color:#403f4c}.td-box--8 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#403f4c transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--8 p>a{color:#d9e5f8}.td-box--18.td-box--gradient{background:#403F4C -webkit-gradient(linear,left top,left bottom,from(#5d5c67),to(#403F4C)) repeat-x!important;background:#403f4c -webkit-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c -o-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c linear-gradient(180deg,#5d5c67,#403F4C) repeat-x!important}.td-box--9{color:#fff;background-color:#ed6a5a}.td-box--9 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ed6a5a transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--9 p>a{color:#a5c3ee}.td-box--19.td-box--gradient{background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x!important;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x!important}.td-box--10{color:#fff;background-color:#30638e}.td-box--10 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#30638e transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--10 p>a{color:#cadcf5}.td-box--110.td-box--gradient{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x!important;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x!important}.td-box--11{color:#fff;background-color:#ffa630}.td-box--11 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ffa630 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--11 p>a{color:#abc7f0}.td-box--111.td-box--gradient{background:#FFA630 -webkit-gradient(linear,left top,left bottom,from(#ffb34f),to(#FFA630)) repeat-x!important;background:#ffa630 -webkit-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 -o-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 linear-gradient(180deg,#ffb34f,#FFA630) repeat-x!important}.td-box--12{color:#222;background-color:#fff}.td-box--12 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#fff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--12 p>a{color:#72a1e5}.td-box--112.td-box--gradient{background:white -webkit-gradient(linear,left top,left bottom,from(white),to(white)) repeat-x!important;background:#fff -webkit-linear-gradient(top,white,white) repeat-x!important;background:#fff -o-linear-gradient(top,white,white) repeat-x!important;background:#fff linear-gradient(180deg,white,white) repeat-x!important}.td-box--13{color:#222;background-color:#c0e0de}.td-box--13 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#c0e0de transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--13 p>a{color:#638ac1}.td-box--113.td-box--gradient{background:#C0E0DE -webkit-gradient(linear,left top,left bottom,from(#c9e5e3),to(#C0E0DE)) repeat-x!important;background:#c0e0de -webkit-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de -o-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de linear-gradient(180deg,#c9e5e3,#C0E0DE) repeat-x!important}.td-box--cerulean-blue{color:#fff;background-color:#017cee}.td-box--cerulean-blue .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#017cee transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--cerulean-blue p>a{color:#bdd3f3}.td-box--1cerulean-blue.td-box--gradient{background:#017cee -webkit-gradient(linear,left top,left bottom,from(#2790f1),to(#017cee)) repeat-x!important;background:#017cee -webkit-linear-gradient(top,#2790f1,#017cee) repeat-x!important;background:#017cee -o-linear-gradient(top,#2790f1,#017cee) repeat-x!important;background:#017cee linear-gradient(180deg,#2790f1,#017cee) repeat-x!important}.td-box--shamrock{color:#fff;background-color:#00ad46}.td-box--shamrock .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#00ad46 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--shamrock p>a{color:#cfdff6}.td-box--1shamrock.td-box--gradient{background:#00ad46 -webkit-gradient(linear,left top,left bottom,from(#26b962),to(#00ad46)) repeat-x!important;background:#00ad46 -webkit-linear-gradient(top,#26b962,#00ad46) repeat-x!important;background:#00ad46 -o-linear-gradient(top,#26b962,#00ad46) repeat-x!important;background:#00ad46 linear-gradient(180deg,#26b962,#00ad46) repeat-x!important}.td-box--bright-sky-blue{color:#fff;background-color:#0cb6ff}.td-box--bright-sky-blue .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#0cb6ff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--bright-sky-blue p>a{color:#b5cef1}.td-box--1bright-sky-blue.td-box--gradient{background:#0cb6ff -webkit-gradient(linear,left top,left bottom,from(#30c1ff),to(#0cb6ff)) repeat-x!important;background:#0cb6ff -webkit-linear-gradient(top,#30c1ff,#0cb6ff) repeat-x!important;background:#0cb6ff -o-linear-gradient(top,#30c1ff,#0cb6ff) repeat-x!important;background:#0cb6ff linear-gradient(180deg,#30c1ff,#0cb6ff) repeat-x!important}.td-box--melon{color:#fff;background-color:#ff7557}.td-box--melon .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ff7557 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--melon p>a{color:#a0c0ee}.td-box--1melon.td-box--gradient{background:#ff7557 -webkit-gradient(linear,left top,left bottom,from(#ff8a70),to(#ff7557)) repeat-x!important;background:#ff7557 -webkit-linear-gradient(top,#ff8a70,#ff7557) repeat-x!important;background:#ff7557 -o-linear-gradient(top,#ff8a70,#ff7557) repeat-x!important;background:#ff7557 linear-gradient(180deg,#ff8a70,#ff7557) repeat-x!important}.td-box--vermillion{color:#fff;background-color:#e43921}.td-box--vermillion .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#e43921 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--vermillion p>a{color:#b7cff2}.td-box--1vermillion.td-box--gradient{background:#e43921 -webkit-gradient(linear,left top,left bottom,from(#e85742),to(#e43921)) repeat-x!important;background:#e43921 -webkit-linear-gradient(top,#e85742,#e43921) repeat-x!important;background:#e43921 -o-linear-gradient(top,#e85742,#e43921) repeat-x!important;background:#e43921 linear-gradient(180deg,#e85742,#e43921) repeat-x!important}.td-box--aqua{color:#fff;background-color:#11e1ee}.td-box--aqua .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#11e1ee transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--aqua p>a{color:#b9d0f2}.td-box--1aqua.td-box--gradient{background:#11e1ee -webkit-gradient(linear,left top,left bottom,from(#35e6f1),to(#11e1ee)) repeat-x!important;background:#11e1ee -webkit-linear-gradient(top,#35e6f1,#11e1ee) repeat-x!important;background:#11e1ee -o-linear-gradient(top,#35e6f1,#11e1ee) repeat-x!important;background:#11e1ee linear-gradient(180deg,#35e6f1,#11e1ee) repeat-x!important}.td-box--shamrock-green{color:#fff;background-color:#04d659}.td-box--shamrock-green .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#04d659 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--shamrock-green p>a{color:#c3d7f4}.td-box--1shamrock-green.td-box--gradient{background:#04d659 -webkit-gradient(linear,left top,left bottom,from(#2adc72),to(#04d659)) repeat-x!important;background:#04d659 -webkit-linear-gradient(top,#2adc72,#04d659) repeat-x!important;background:#04d659 -o-linear-gradient(top,#2adc72,#04d659) repeat-x!important;background:#04d659 linear-gradient(180deg,#2adc72,#04d659) repeat-x!important}.td-box--aqua-blue{color:#fff;background-color:#00c7d4}.td-box--aqua-blue .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#00c7d4 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--aqua-blue p>a{color:#c4d8f4}.td-box--1aqua-blue.td-box--gradient{background:#00c7d4 -webkit-gradient(linear,left top,left bottom,from(#26cfda),to(#00c7d4)) repeat-x!important;background:#00c7d4 -webkit-linear-gradient(top,#26cfda,#00c7d4) repeat-x!important;background:#00c7d4 -o-linear-gradient(top,#26cfda,#00c7d4) repeat-x!important;background:#00c7d4 linear-gradient(180deg,#26cfda,#00c7d4) repeat-x!important}.td-box--white{color:#222;background-color:#fff}.td-box--white .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#fff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--white p>a{color:#72a1e5}.td-box--1white.td-box--gradient{background:#ffffff -webkit-gradient(linear,left top,left bottom,from(white),to(#ffffff)) repeat-x!important;background:#fff -webkit-linear-gradient(top,white,#ffffff) repeat-x!important;background:#fff -o-linear-gradient(top,white,#ffffff) repeat-x!important;background:#fff linear-gradient(180deg,white,#ffffff) repeat-x!important}.td-box--brownish-grey{color:#fff;background-color:#707070}.td-box--brownish-grey .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#707070 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--brownish-grey p>a{color:#c1d6f4}.td-box--1brownish-grey.td-box--gradient{background:#707070 -webkit-gradient(linear,left top,left bottom,from(#858585),to(#707070)) repeat-x!important;background:#707070 -webkit-linear-gradient(top,#858585,#707070) repeat-x!important;background:#707070 -o-linear-gradient(top,#858585,#707070) repeat-x!important;background:#707070 linear-gradient(180deg,#858585,#707070) repeat-x!important}.td-box--very-light-pink{color:#222;background-color:#cbcbcb}.td-box--very-light-pink .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#cbcbcb transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--very-light-pink p>a{color:#6287bd}.td-box--1very-light-pink.td-box--gradient{background:#cbcbcb -webkit-gradient(linear,left top,left bottom,from(lightgray),to(#cbcbcb)) repeat-x!important;background:#cbcbcb -webkit-linear-gradient(top,lightgray,#cbcbcb) repeat-x!important;background:#cbcbcb -o-linear-gradient(top,lightgray,#cbcbcb) repeat-x!important;background:#cbcbcb linear-gradient(180deg,lightgray,#cbcbcb) repeat-x!important}.td-box--slate-grey{color:#fff;background-color:#636365}.td-box--slate-grey .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#636365 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--slate-grey p>a{color:#c8daf5}.td-box--1slate-grey.td-box--gradient{background:#636365 -webkit-gradient(linear,left top,left bottom,from(#7a7a7c),to(#636365)) repeat-x!important;background:#636365 -webkit-linear-gradient(top,#7a7a7c,#636365) repeat-x!important;background:#636365 -o-linear-gradient(top,#7a7a7c,#636365) repeat-x!important;background:#636365 linear-gradient(180deg,#7a7a7c,#636365) repeat-x!important}.td-box--greyish-brown{color:#fff;background-color:#51504f}.td-box--greyish-brown .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#51504f transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--greyish-brown p>a{color:#d3e2f7}.td-box--1greyish-brown.td-box--gradient{background:#51504f -webkit-gradient(linear,left top,left bottom,from(#6b6a69),to(#51504f)) repeat-x!important;background:#51504f -webkit-linear-gradient(top,#6b6a69,#51504f) repeat-x!important;background:#51504f -o-linear-gradient(top,#6b6a69,#51504f) repeat-x!important;background:#51504f linear-gradient(180deg,#6b6a69,#51504f) repeat-x!important}.td-box--primary{color:#fff;background-color:#30638e}.td-box--primary .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#30638e transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--primary p>a{color:#cadcf5}.td-box--1primary.td-box--gradient{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x!important;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x!important}.td-box--secondary{color:#fff;background-color:#ffa630}.td-box--secondary .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ffa630 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--secondary p>a{color:#abc7f0}.td-box--1secondary.td-box--gradient{background:#FFA630 -webkit-gradient(linear,left top,left bottom,from(#ffb34f),to(#FFA630)) repeat-x!important;background:#ffa630 -webkit-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 -o-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 linear-gradient(180deg,#ffb34f,#FFA630) repeat-x!important}.td-box--success{color:#fff;background-color:#3772ff}.td-box--success .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#3772ff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--success p>a{color:#a9c6ef}.td-box--1success.td-box--gradient{background:#3772FF -webkit-gradient(linear,left top,left bottom,from(#5587ff),to(#3772FF)) repeat-x!important;background:#3772ff -webkit-linear-gradient(top,#5587ff,#3772FF) repeat-x!important;background:#3772ff -o-linear-gradient(top,#5587ff,#3772FF) repeat-x!important;background:#3772ff linear-gradient(180deg,#5587ff,#3772FF) repeat-x!important}.td-box--info{color:#222;background-color:#c0e0de}.td-box--info .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#c0e0de transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--info p>a{color:#638ac1}.td-box--1info.td-box--gradient{background:#C0E0DE -webkit-gradient(linear,left top,left bottom,from(#c9e5e3),to(#C0E0DE)) repeat-x!important;background:#c0e0de -webkit-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de -o-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de linear-gradient(180deg,#c9e5e3,#C0E0DE) repeat-x!important}.td-box--warning{color:#fff;background-color:#ed6a5a}.td-box--warning .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ed6a5a transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--warning p>a{color:#a5c3ee}.td-box--1warning.td-box--gradient{background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x!important;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x!important}.td-box--danger{color:#fff;background-color:#ed6a5a}.td-box--danger .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ed6a5a transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--danger p>a{color:#a5c3ee}.td-box--1danger.td-box--gradient{background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x!important;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x!important}.td-box--light{color:#222;background-color:#d3f3ee}.td-box--light .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#d3f3ee transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--light p>a{color:#6993d0}.td-box--1light.td-box--gradient{background:#D3F3EE -webkit-gradient(linear,left top,left bottom,from(#daf5f1),to(#D3F3EE)) repeat-x!important;background:#d3f3ee -webkit-linear-gradient(top,#daf5f1,#D3F3EE) repeat-x!important;background:#d3f3ee -o-linear-gradient(top,#daf5f1,#D3F3EE) repeat-x!important;background:#d3f3ee linear-gradient(180deg,#daf5f1,#D3F3EE) repeat-x!important}.td-box--dark{color:#fff;background-color:#403f4c}.td-box--dark .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#403f4c transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--dark p>a{color:#d9e5f8}.td-box--1dark.td-box--gradient{background:#403F4C -webkit-gradient(linear,left top,left bottom,from(#5d5c67),to(#403F4C)) repeat-x!important;background:#403f4c -webkit-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c -o-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c linear-gradient(180deg,#5d5c67,#403F4C) repeat-x!important}.td-box--100{color:#222;background-color:#f8f9fa}.td-box--100 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#f8f9fa transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--100 p>a{color:#709ee0}.td-box--1100.td-box--gradient{background:#f8f9fa -webkit-gradient(linear,left top,left bottom,from(#f9fafb),to(#f8f9fa)) repeat-x!important;background:#f8f9fa -webkit-linear-gradient(top,#f9fafb,#f8f9fa) repeat-x!important;background:#f8f9fa -o-linear-gradient(top,#f9fafb,#f8f9fa) repeat-x!important;background:#f8f9fa linear-gradient(180deg,#f9fafb,#f8f9fa) repeat-x!important}.td-box--200{color:#222;background-color:#eee}.td-box--200 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#eee transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--200 p>a{color:#6d99d8}.td-box--1200.td-box--gradient{background:#eee -webkit-gradient(linear,left top,left bottom,from(#f1f1f1),to(#eee)) repeat-x!important;background:#eee -webkit-linear-gradient(top,#f1f1f1,#eee) repeat-x!important;background:#eee -o-linear-gradient(top,#f1f1f1,#eee) repeat-x!important;background:#eee linear-gradient(180deg,#f1f1f1,#eee) repeat-x!important}.td-box--300{color:#222;background-color:#dee2e6}.td-box--300 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#dee2e6 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--300 p>a{color:#6993cf}.td-box--1300.td-box--gradient{background:#dee2e6 -webkit-gradient(linear,left top,left bottom,from(#e3e6ea),to(#dee2e6)) repeat-x!important;background:#dee2e6 -webkit-linear-gradient(top,#e3e6ea,#dee2e6) repeat-x!important;background:#dee2e6 -o-linear-gradient(top,#e3e6ea,#dee2e6) repeat-x!important;background:#dee2e6 linear-gradient(180deg,#e3e6ea,#dee2e6) repeat-x!important}.td-box--400{color:#222;background-color:#ccc}.td-box--400 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ccc transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--400 p>a{color:#6288be}.td-box--1400.td-box--gradient{background:#ccc -webkit-gradient(linear,left top,left bottom,from(#d4d4d4),to(#ccc)) repeat-x!important;background:#ccc -webkit-linear-gradient(top,#d4d4d4,#ccc) repeat-x!important;background:#ccc -o-linear-gradient(top,#d4d4d4,#ccc) repeat-x!important;background:#ccc linear-gradient(180deg,#d4d4d4,#ccc) repeat-x!important}.td-box--500{color:#fff;background-color:#adb5bd}.td-box--500 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#adb5bd transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--500 p>a{color:#9bbced}.td-box--1500.td-box--gradient{background:#adb5bd -webkit-gradient(linear,left top,left bottom,from(#b9c0c7),to(#adb5bd)) repeat-x!important;background:#adb5bd -webkit-linear-gradient(top,#b9c0c7,#adb5bd) repeat-x!important;background:#adb5bd -o-linear-gradient(top,#b9c0c7,#adb5bd) repeat-x!important;background:#adb5bd linear-gradient(180deg,#b9c0c7,#adb5bd) repeat-x!important}.td-box--600{color:#fff;background-color:#888}.td-box--600 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#888 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--600 p>a{color:#b4cdf1}.td-box--1600.td-box--gradient{background:#888 -webkit-gradient(linear,left top,left bottom,from(#9a9a9a),to(#888)) repeat-x!important;background:#888 -webkit-linear-gradient(top,#9a9a9a,#888) repeat-x!important;background:#888 -o-linear-gradient(top,#9a9a9a,#888) repeat-x!important;background:#888 linear-gradient(180deg,#9a9a9a,#888) repeat-x!important}.td-box--700{color:#fff;background-color:#495057}.td-box--700 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#495057 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--700 p>a{color:#d3e2f7}.td-box--1700.td-box--gradient{background:#495057 -webkit-gradient(linear,left top,left bottom,from(#646a70),to(#495057)) repeat-x!important;background:#495057 -webkit-linear-gradient(top,#646a70,#495057) repeat-x!important;background:#495057 -o-linear-gradient(top,#646a70,#495057) repeat-x!important;background:#495057 linear-gradient(180deg,#646a70,#495057) repeat-x!important}.td-box--800{color:#fff;background-color:#333}.td-box--800 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#333 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--800 p>a{color:#e3ecfa}.td-box--1800.td-box--gradient{background:#333 -webkit-gradient(linear,left top,left bottom,from(#525252),to(#333)) repeat-x!important;background:#333 -webkit-linear-gradient(top,#525252,#333) repeat-x!important;background:#333 -o-linear-gradient(top,#525252,#333) repeat-x!important;background:#333 linear-gradient(180deg,#525252,#333) repeat-x!important}.td-box--900{color:#fff;background-color:#222}.td-box--900 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#222 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--900 p>a{color:#ecf2fc}.td-box--1900.td-box--gradient{background:#222 -webkit-gradient(linear,left top,left bottom,from(#434343),to(#222)) repeat-x!important;background:#222 -webkit-linear-gradient(top,#434343,#222) repeat-x!important;background:#222 -o-linear-gradient(top,#434343,#222) repeat-x!important;background:#222 linear-gradient(180deg,#434343,#222) repeat-x!important}.td-blog .td-rss-button{position:absolute;top:5.5rem;right:1rem;z-index:22}.td-content .highlight{margin:2rem 0;padding:1rem;background-color:#f8f9fa}.td-content .highlight pre,.td-content .highlight div{background-color:inherit!important}.td-content .highlight pre{margin:0;padding:0}.td-content p code,.td-content li>code,.td-content table code{color:inherit;padding:.2em .4em;margin:0;font-size:85%;word-break:normal;background-color:rgba(0,0,0,.05);border-radius:.25rem}.td-content p code br,.td-content li>code br,.td-content table code br{display:none}.td-content pre{word-wrap:normal;background-color:#f8f9fa;padding:1rem}.td-content pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;border:0}.td-navbar-cover{background:#30638e}@media(min-width:768px){.td-navbar-cover{background:transparent!important}.td-navbar-cover .nav-link{text-shadow:1px 1px 2px #403f4c}}.td-navbar-cover.navbar-bg-onscroll .nav-link{text-shadow:none}.navbar-bg-onscroll{background:#30638e!important;opacity:inherit}.td-navbar{background:#30638e;min-height:4rem;margin:0;z-index:32}@media(min-width:768px){.td-navbar{position:fixed;top:0;width:100%}}.td-navbar .navbar-brand{text-transform:none;text-align:middle}.td-navbar .navbar-brand .nav-link{display:inline-block;margin-right:-30px}.td-navbar .navbar-brand svg{display:inline-block;margin:0 10px;height:30px}.td-navbar .nav-link{text-transform:none;font-weight:700}.td-navbar .td-search-input{border:none}.td-navbar .td-search-input::-webkit-input-placeholder{color:rgba(255,255,255,.75)}.td-navbar .td-search-input:-moz-placeholder{color:rgba(255,255,255,.75)}.td-navbar .td-search-input::-moz-placeholder{color:rgba(255,255,255,.75)}.td-navbar .td-search-input:-ms-input-placeholder{color:rgba(255,255,255,.75)}.td-navbar .dropdown{min-width:100px}@media(max-width:991.98px){.td-navbar{padding-right:.5rem;padding-left:.75rem}.td-navbar .td-navbar-nav-scroll{max-width:100%;height:2.5rem;margin-top:.25rem;overflow:hidden;font-size:.875rem}.td-navbar .td-navbar-nav-scroll .nav-link{padding-right:.25rem;padding-left:0}.td-navbar .td-navbar-nav-scroll .navbar-nav{padding-bottom:2rem;overflow-x:auto;white-space:nowrap;-webkit-overflow-scrolling:touch}}.td-sidebar-nav{padding-right:.5rem;margin-right:-15px;margin-left:-15px}@media(min-width:768px){@supports((position:-webkit-sticky) or (position:sticky)){.td-sidebar-nav{max-height:-webkit-calc(100vh - 10rem);max-height:calc(100vh - 10rem);overflow-y:auto}}}@media(min-width:768px){.td-sidebar-nav{display:block!important}}.td-sidebar-nav__section{padding-left:0}.td-sidebar-nav__section li{list-style:none}.td-sidebar-nav__section ul{padding:0;margin:0}@media(min-width:768px){.td-sidebar-nav__section>ul{padding-left:.5rem}}.td-sidebar-nav__section-title{display:block;font-weight:500}.td-sidebar-nav__section-title .active{font-weight:700}.td-sidebar-nav__section-title a{color:#222}.td-sidebar-nav .td-sidebar-link{display:block;padding-bottom:.375rem}.td-sidebar-nav .td-sidebar-link__page{color:#495057;font-weight:300}.td-sidebar-nav a:hover{color:#72a1e5;text-decoration:none}.td-sidebar-nav a.active{font-weight:700}.td-sidebar-nav .dropdown a{color:#495057}.td-sidebar-nav .dropdown .nav-link{padding:0 0 1rem}.td-sidebar{padding-bottom:1rem}@media(min-width:768px){.td-sidebar{padding-top:4rem;background-color:rgba(48,99,142,.03);padding-right:1rem;border-right:1px solid #dee2e6}}.td-sidebar__toggle{line-height:1;color:#222;margin:1rem}.td-sidebar__search{padding:1rem 15px;margin-right:-15px;margin-left:-15px}.td-sidebar__inner{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}@media(min-width:768px){@supports((position:-webkit-sticky) or (position:sticky)){.td-sidebar__inner{position:-webkit-sticky;position:sticky;top:4rem;z-index:10;height:-webkit-calc(100vh - 6rem);height:calc(100vh - 6rem)}}}@media(min-width:1200px){.td-sidebar__inner{-webkit-box-flex:0;-webkit-flex:0 1 320px;-ms-flex:0 1 320px;flex:0 1 320px}}.td-sidebar__inner .td-search-box{width:100%}.td-toc{border-left:1px solid #dee2e6;-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2;padding-top:.75rem;padding-bottom:1.5rem;vertical-align:top}@supports((position:-webkit-sticky) or (position:sticky)){.td-toc{position:-webkit-sticky;position:sticky;top:4rem;height:-webkit-calc(100vh - 10rem);height:calc(100vh - 10rem);overflow-y:auto}}.td-toc a{display:block;font-weight:300;padding-bottom:.25rem}.td-toc li{list-style:none;display:block}.td-toc li li{margin-left:.5rem}.td-toc .td-page-meta a{font-weight:500}.td-toc #TableOfContents a{color:#888}.td-toc #TableOfContents a:hover{color:#72a1e5;text-decoration:none}.td-toc ul{padding-left:0}button{cursor:pointer;border:1px solid;border-radius:5px;padding:9px 29px;-webkit-transition:all ease-out .2s;-o-transition:all ease-out .2s;transition:all ease-out .2s}button:disabled{cursor:not-allowed}button.btn-filled{border-color:#017cee;background-color:#017cee}button.btn-filled:hover{border-color:#0cb6ff;background-color:#0cb6ff}button.btn-with-icon{padding:14px 20px}button.btn-with-icon svg{height:30px;width:auto;padding-right:15px}button.btn-with-icon span{display:inline-block;line-height:30px;vertical-align:middle}button.btn-hollow{background-color:#fff}button.btn-hollow.btn-blue{color:#017cee;border-color:#017cee}button.btn-hollow.btn-blue:disabled{color:#cbcbcb;border-color:#cbcbcb}button.btn-hollow.btn-blue:hover:enabled{color:#fff;background-color:#017cee}button.btn-hollow.btn-brown{border-color:#cbcbcb}button.btn-hollow.btn-brown:hover{background-color:#51504f;border-color:#51504f}button.btn-hollow.btn-brown:hover span{color:#fff}button.btn-hollow.btn-brown:hover svg path{fill:#fff}button.with-box-shadow{-webkit-box-shadow:0 2px 6px 0 rgba(0,0,0,.12);box-shadow:0 2px 6px 0 rgba(0,0,0,.12)}@media(max-width:1280px){button{padding:4px 17px}}.breadcrumb{background:0 0;padding-left:0;padding-top:0}.alert{font-weight:500;background:#fff;color:inherit;border-radius:0}.alert-primary{border-style:solid;border-color:#30638e;border-width:0 0 0 4px}.alert-primary .alert-heading{color:#30638e}.alert-secondary{border-style:solid;border-color:#ffa630;border-width:0 0 0 4px}.alert-secondary .alert-heading{color:#ffa630}.alert-success{border-style:solid;border-color:#3772ff;border-width:0 0 0 4px}.alert-success .alert-heading{color:#3772ff}.alert-info{border-style:solid;border-color:#c0e0de;border-width:0 0 0 4px}.alert-info .alert-heading{color:#c0e0de}.alert-warning{border-style:solid;border-color:#ed6a5a;border-width:0 0 0 4px}.alert-warning .alert-heading{color:#ed6a5a}.alert-danger{border-style:solid;border-color:#ed6a5a;border-width:0 0 0 4px}.alert-danger .alert-heading{color:#ed6a5a}.alert-light{border-style:solid;border-color:#d3f3ee;border-width:0 0 0 4px}.alert-light .alert-heading{color:#d3f3ee}.alert-dark{border-style:solid;border-color:#403f4c;border-width:0 0 0 4px}.alert-dark .alert-heading{color:#403f4c}.td-content{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.td-content p,.td-content li,.td-content td{font-weight:400}.td-content>h1{font-weight:700;margin-bottom:1rem}.td-content>h2{margin-bottom:1rem}.td-content>h2:not(:first-child){margin-top:3rem}.td-content>h2+h3{margin-top:1rem}.td-content>h3,.td-content>h4,.td-content>h5,.td-content>h6{margin-bottom:1rem;margin-top:2rem}.td-content>blockquote{padding:0 0 0 1rem;margin-bottom:1rem;color:#888;border-left:6px solid #ffa630}.td-content>ul li,.td-content>ol li{margin-bottom:.25rem}.td-content strong{font-weight:700}.td-content .alert:not(:first-child){margin-top:2rem;margin-bottom:2rem}.td-content .lead{margin-bottom:1.5rem}.td-title{margin-top:1rem;margin-bottom:.5rem}@media(min-width:576px){.td-title{font-size:3rem}}.search-form{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:344px;padding:8px 20px;border:solid 1px #cbcbcb;border-radius:5px;margin:60px auto 0}.search-form__input{font-family:roboto,sans-serif;font-size:16px;color:#707070;line-height:1.63;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;padding-right:10px;border:none;background:0 0;outline:none;float:left}.search-form__button{border:none;background-color:transparent;padding:0}@media(max-width:1280px){.search-form{width:270px;padding:3px 20px;margin-top:30px}}.td-outer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;height:100vh}@media(min-width:768px){.td-default main section:first-of-type{padding-top:8rem}}.td-main{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1}.td-main main{padding-bottom:2rem}@media(min-width:768px){.td-main main{padding-top:5.5rem}}.td-cover-block--height-min{min-height:300px}.td-cover-block--height-med{min-height:400px}.td-cover-block--height-max{min-height:500px}.td-cover-block--height-full{min-height:100vh}@media(min-width:768px){.td-cover-block--height-min{min-height:450px}.td-cover-block--height-med{min-height:500px}.td-cover-block--height-max{min-height:650px}}.td-cover-logo{margin-right:.5em}.td-cover-block{position:relative;padding-top:5rem;padding-bottom:5rem;background-repeat:no-repeat;background-position:50% 0;-webkit-background-size:cover;background-size:cover}.td-bg-arrow-wrapper{position:relative}.section-index .entry{padding:.75rem}.section-index h5{margin-bottom:0}.section-index h5 a{font-weight:700}.section-index p{margin-top:0}.pageinfo{font-weight:500;background:#f8f9fa;color:inherit;border-radius:0;margin:2rem;padding:1.5rem;padding-bottom:.5rem}.pageinfo-primary{border-style:solid;border-color:#30638e}.pageinfo-secondary{border-style:solid;border-color:#ffa630}.pageinfo-success{border-style:solid;border-color:#3772ff}.pageinfo-info{border-style:solid;border-color:#c0e0de}.pageinfo-warning{border-style:solid;border-color:#ed6a5a}.pageinfo-danger{border-style:solid;border-color:#ed6a5a}.pageinfo-light{border-style:solid;border-color:#d3f3ee}.pageinfo-dark{border-style:solid;border-color:#403f4c}footer{min-height:150px}@media(max-width:991.98px){footer{min-height:200px}}@media(min-width:768px){.td-offset-anchor:target{display:block;position:relative;top:-4rem;visibility:hidden}h2[id]:before,h3[id]:before,h4[id]:before,h5[id]:before{display:block;content:" ";margin-top:-5rem;height:5rem;visibility:hidden}} \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/_gen/js/docs.js b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/_gen/js/docs.js new file mode 100644 index 00000000000..90898d86d50 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/_gen/js/docs.js @@ -0,0 +1 @@ +!function(r){var n={};function o(t){if(n[t])return n[t].exports;var e=n[t]={i:t,l:!1,exports:{}};return r[t].call(e.exports,e,e.exports,o),e.l=!0,e.exports}o.m=r,o.c=n,o.d=function(t,e,r){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(o.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)o.d(r,n,function(t){return e[t]}.bind(null,n));return r},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o.p="/",o(o.s=54)}([function(t,e,r){var m=r(1),w=r(14),g=r(15),E=Math.max,x=Math.min;t.exports=function(n,r,t){var o,i,a,s,u,c,f=0,l=!1,d=!1,e=!0;if("function"!=typeof n)throw new TypeError("Expected a function");function h(t){var e=o,r=i;return o=i=void 0,f=t,s=n.apply(r,e)}function p(t){var e=t-c;return void 0===c||r<=e||e<0||d&&a<=t-f}function y(){var t=w();if(p(t))return b(t);u=setTimeout(y,function(t){var e=r-(t-c);return d?x(e,a-(t-f)):e}(t))}function b(t){return u=void 0,e&&o?h(t):(o=i=void 0,s)}function v(){var t=w(),e=p(t);if(o=arguments,i=this,c=t,e){if(void 0===u)return function(t){return f=t,u=setTimeout(y,r),l?h(t):s}(c);if(d)return clearTimeout(u),u=setTimeout(y,r),h(c)}return void 0===u&&(u=setTimeout(y,r)),s}return r=g(r)||0,m(t)&&(l=!!t.leading,a=(d="maxWait"in t)?E(g(t.maxWait)||0,r):a,e="trailing"in t?!!t.trailing:e),v.cancel=function(){void 0!==u&&clearTimeout(u),o=c=i=u=void(f=0)},v.flush=function(){return void 0===u?s:b(w())},v}},function(t,e){t.exports=function(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}},function(t,e,r){var n=r(8),o="object"==typeof self&&self&&self.Object===Object&&self,i=n||o||Function("return this")();t.exports=i},function(t,e,r){var n=r(6),o=r(17),i=r(18),a=n?n.toStringTag:void 0;t.exports=function(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":a&&a in Object(t)?o(t):i(t)}},function(t,e){t.exports=function(t){return null!=t&&"object"==typeof t}},function(t,e,r){!function(s){"use strict";var u={searchParams:"URLSearchParams"in self,iterable:"Symbol"in self&&"iterator"in Symbol,blob:"FileReader"in self&&"Blob"in self&&function(){try{return new Blob,!0}catch(t){return!1}}(),formData:"FormData"in self,arrayBuffer:"ArrayBuffer"in self};if(u.arrayBuffer)var e=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],r=ArrayBuffer.isView||function(t){return t&&-1 nav").offsetHeight,n=function(){var t;e.sort(function(t,e){return t.targetElement.offsetTop-e.targetElement.offsetTop}),t=e[0].targetElement.offsetTop+r>window.scrollY?0:e[e.length-1].targetElement.offsetTop+rwindow.scrollY})-1,e.forEach(function(t){return t.navElement.classList.remove("current")}),e[t].navElement.classList.add("current")};window.addEventListener("scroll",o()(n,10)),window.addEventListener("resize",o()(n,10)),n()}}()},function(t,e,r){var n=r(2);t.exports=function(){return n.Date.now()}},function(t,e,r){var n=r(1),o=r(16),i=/^\s+|\s+$/g,a=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,u=/^0o[0-7]+$/i,c=parseInt;t.exports=function(t){if("number"==typeof t)return t;if(o(t))return NaN;if(n(t)){var e="function"==typeof t.valueOf?t.valueOf():t;t=n(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=t.replace(i,"");var r=s.test(t);return r||u.test(t)?c(t.slice(2),r?2:8):a.test(t)?NaN:+t}},function(t,e,r){var n=r(3),o=r(4);t.exports=function(t){return"symbol"==typeof t||o(t)&&"[object Symbol]"==n(t)}},function(t,e,r){var n=r(6),o=Object.prototype,i=o.hasOwnProperty,a=o.toString,s=n?n.toStringTag:void 0;t.exports=function(t){var e=i.call(t,s),r=t[s];try{var n=!(t[s]=void 0)}catch(t){}var o=a.call(t);return n&&(e?t[s]=r:delete t[s]),o}},function(t,e){var r=Object.prototype.toString;t.exports=function(t){return r.call(t)}},function(t,e){!function(){var e=window.document.querySelector(".rating");if(e){function t(t){e.querySelector("#rate-star-".concat(t)).addEventListener("click",function(){!function(t){window._paq.push(["trackEvent","Docs","Rating",window.location.pathname,t])}(t),e.innerHTML="

Thank you!

"})}for(var r=1;r<=5;r++)t(r)}}()},function(t,e){var r=window.document.querySelector(".rst-content");!function(){if(r){var t=r.querySelectorAll("table");t&&0!==t.length&&t.forEach(function(t){if(!t.parentNode.classList.contains("wy-table-responsive")){var e=document.createElement("div");e.classList.add("wy-table-responsive"),t.parentNode.insertBefore(e,t),e.appendChild(t)}})}}()},function(t,e,n){"use strict";(function(t){var i=n(7);function r(t){return function(t){if(Array.isArray(t))return t}(t)||function(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}(t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function f(){var t=r(document.location.pathname.split("/")),e=t[2];return{currentVersion:t[3],currentPackageName:e,pagePath:t.slice(4).join("/")}}var a;(a=window.document.querySelectorAll(".docs-version-selector"))&&0!==a.length&&t("/_gen/packages-metadata.json").then(function(t){return t.json()}).then(function(t){var e=f().currentPackageName,r=t.find(function(t){return t["package-name"]===e});if(r){var n=r["all-versions"].sort(i.a).reverse(),o=r["stable-version"];a.forEach(function(t){return function(t,e,r){var n=t.querySelector("#version-item-template").innerText,o=document.createElement("div");function i(t,e){var r=o.cloneNode(!0),n="/docs/".concat(u,"/").concat(t,"/").concat(c);r.setAttribute("href",n),r.innerText=e,a.appendChild(r)}o.innerHTML=n,o=o.firstElementChild;var a=t.querySelector(".dropdown-menu"),s=f(),u=s.currentPackageName,c=s.pagePath;i("stable","Stable (".concat(r,")")),e.forEach(function(t){return i(t,t)})}(t,n,o)})}})}).call(this,n(5))},,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,function(t,e,r){"use strict";r.r(e);r(10),r(11),r(12),r(13),r(19),r(20),r(55),r(21)},function(t,e){Array.from(document.querySelectorAll(".toctree ul")).forEach(function(t){Array.from(t.parentNode.children).filter(function(t){return"A"===t.tagName}).forEach(function(t){var e=document.createElement("span");e.classList.add("toctree-expand"),t.insertBefore(e,t.firstChild)})})}]); \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/_sphinx_javascript_frameworks_compat.js b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/_sphinx_javascript_frameworks_compat.js new file mode 100644 index 00000000000..8549469dc29 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/_sphinx_javascript_frameworks_compat.js @@ -0,0 +1,134 @@ +/* + * _sphinx_javascript_frameworks_compat.js + * ~~~~~~~~~~ + * + * Compatability shim for jQuery and underscores.js. + * + * WILL BE REMOVED IN Sphinx 6.0 + * xref RemovedInSphinx60Warning + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/basic.css b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/basic.css new file mode 100644 index 00000000000..eeb0519a69b --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/basic.css @@ -0,0 +1,899 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} +dl.field-list > dt:after { + content: ":"; +} + + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/check-solid.svg b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/check-solid.svg new file mode 100644 index 00000000000..92fad4b5c0b --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/check-solid.svg @@ -0,0 +1,4 @@ + + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/clipboard.min.js b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/clipboard.min.js new file mode 100644 index 00000000000..54b3c463811 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.8 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1 + + + + diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/copybutton.css b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/copybutton.css new file mode 100644 index 00000000000..f1916ec7d1b --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/copybutton.css @@ -0,0 +1,94 @@ +/* Copy buttons */ +button.copybtn { + position: absolute; + display: flex; + top: .3em; + right: .3em; + width: 1.7em; + height: 1.7em; + opacity: 0; + transition: opacity 0.3s, border .3s, background-color .3s; + user-select: none; + padding: 0; + border: none; + outline: none; + border-radius: 0.4em; + /* The colors that GitHub uses */ + border: #1b1f2426 1px solid; + background-color: #f6f8fa; + color: #57606a; +} + +button.copybtn.success { + border-color: #22863a; + color: #22863a; +} + +button.copybtn svg { + stroke: currentColor; + width: 1.5em; + height: 1.5em; + padding: 0.1em; +} + +div.highlight { + position: relative; +} + +/* Show the copybutton */ +.highlight:hover button.copybtn, button.copybtn.success { + opacity: 1; +} + +.highlight button.copybtn:hover { + background-color: rgb(235, 235, 235); +} + +.highlight button.copybtn:active { + background-color: rgb(187, 187, 187); +} + +/** + * A minimal CSS-only tooltip copied from: + * https://codepen.io/mildrenben/pen/rVBrpK + * + * To use, write HTML like the following: + * + *

Short

+ */ + .o-tooltip--left { + position: relative; + } + + .o-tooltip--left:after { + opacity: 0; + visibility: hidden; + position: absolute; + content: attr(data-tooltip); + padding: .2em; + font-size: .8em; + left: -.2em; + background: grey; + color: white; + white-space: nowrap; + z-index: 2; + border-radius: 2px; + transform: translateX(-102%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); +} + +.o-tooltip--left:hover:after { + display: block; + opacity: 1; + visibility: visible; + transform: translateX(-100%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); + transition-delay: .5s; +} + +/* By default the copy button shouldn't show up when printing a page */ +@media print { + button.copybtn { + display: none; + } +} diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/copybutton.js b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/copybutton.js new file mode 100644 index 00000000000..2ea7ff3e217 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/copybutton.js @@ -0,0 +1,248 @@ +// Localization support +const messages = { + 'en': { + 'copy': 'Copy', + 'copy_to_clipboard': 'Copy to clipboard', + 'copy_success': 'Copied!', + 'copy_failure': 'Failed to copy', + }, + 'es' : { + 'copy': 'Copiar', + 'copy_to_clipboard': 'Copiar al portapapeles', + 'copy_success': '¡Copiado!', + 'copy_failure': 'Error al copiar', + }, + 'de' : { + 'copy': 'Kopieren', + 'copy_to_clipboard': 'In die Zwischenablage kopieren', + 'copy_success': 'Kopiert!', + 'copy_failure': 'Fehler beim Kopieren', + }, + 'fr' : { + 'copy': 'Copier', + 'copy_to_clipboard': 'Copier dans le presse-papier', + 'copy_success': 'Copié !', + 'copy_failure': 'Échec de la copie', + }, + 'ru': { + 'copy': 'Скопировать', + 'copy_to_clipboard': 'Скопировать в буфер', + 'copy_success': 'Скопировано!', + 'copy_failure': 'Не удалось скопировать', + }, + 'zh-CN': { + 'copy': '复制', + 'copy_to_clipboard': '复制到剪贴板', + 'copy_success': '复制成功!', + 'copy_failure': '复制失败', + }, + 'it' : { + 'copy': 'Copiare', + 'copy_to_clipboard': 'Copiato negli appunti', + 'copy_success': 'Copiato!', + 'copy_failure': 'Errore durante la copia', + } +} + +let locale = 'en' +if( document.documentElement.lang !== undefined + && messages[document.documentElement.lang] !== undefined ) { + locale = document.documentElement.lang +} + +let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT; +if (doc_url_root == '#') { + doc_url_root = ''; +} + +/** + * SVG files for our copy buttons + */ +let iconCheck = ` + ${messages[locale]['copy_success']} + + +` + +// If the user specified their own SVG use that, otherwise use the default +let iconCopy = ``; +if (!iconCopy) { + iconCopy = ` + ${messages[locale]['copy_to_clipboard']} + + + +` +} + +/** + * Set up copy/paste for code blocks + */ + +const runWhenDOMLoaded = cb => { + if (document.readyState != 'loading') { + cb() + } else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', cb) + } else { + document.attachEvent('onreadystatechange', function() { + if (document.readyState == 'complete') cb() + }) + } +} + +const codeCellId = index => `codecell${index}` + +// Clears selected text since ClipboardJS will select the text when copying +const clearSelection = () => { + if (window.getSelection) { + window.getSelection().removeAllRanges() + } else if (document.selection) { + document.selection.empty() + } +} + +// Changes tooltip text for a moment, then changes it back +// We want the timeout of our `success` class to be a bit shorter than the +// tooltip and icon change, so that we can hide the icon before changing back. +var timeoutIcon = 2000; +var timeoutSuccessClass = 1500; + +const temporarilyChangeTooltip = (el, oldText, newText) => { + el.setAttribute('data-tooltip', newText) + el.classList.add('success') + // Remove success a little bit sooner than we change the tooltip + // So that we can use CSS to hide the copybutton first + setTimeout(() => el.classList.remove('success'), timeoutSuccessClass) + setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon) +} + +// Changes the copy button icon for two seconds, then changes it back +const temporarilyChangeIcon = (el) => { + el.innerHTML = iconCheck; + setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon) +} + +const addCopyButtonToCodeCells = () => { + // If ClipboardJS hasn't loaded, wait a bit and try again. This + // happens because we load ClipboardJS asynchronously. + if (window.ClipboardJS === undefined) { + setTimeout(addCopyButtonToCodeCells, 250) + return + } + + // Add copybuttons to all of our code cells + const COPYBUTTON_SELECTOR = 'div.highlight pre'; + const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR) + codeCells.forEach((codeCell, index) => { + const id = codeCellId(index) + codeCell.setAttribute('id', id) + + const clipboardButton = id => + `` + codeCell.insertAdjacentHTML('afterend', clipboardButton(id)) + }) + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} + + +var copyTargetText = (trigger) => { + var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); + + // get filtered text + let exclude = '.linenos'; + + let text = filterText(target, exclude); + return formatCopyText(text, '', false, true, true, true, '', '') +} + + // Initialize with a callback so we can modify the text before copy + const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText}) + + // Update UI with error/success messages + clipboard.on('success', event => { + clearSelection() + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success']) + temporarilyChangeIcon(event.trigger) + }) + + clipboard.on('error', event => { + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure']) + }) +} + +runWhenDOMLoaded(addCopyButtonToCodeCells) \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/copybutton_funcs.js b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/copybutton_funcs.js new file mode 100644 index 00000000000..dbe1aaad79c --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/copybutton_funcs.js @@ -0,0 +1,73 @@ +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +export function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/custom.css b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/custom.css new file mode 100644 index 00000000000..b1cf49f37d4 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/custom.css @@ -0,0 +1,33 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + /* + This file contains style overrides for the sphinx-design extension. + + The original defaults can be found here: + https://sphinx-design.readthedocs.io/en/alabaster-theme/css_variables.html + */ + +:root { + --sd-color-tabs-label-active: #017cee; + --sd-color-tabs-label-hover: #68d1ff; + --sd-color-tabs-underline-active: #017cee; + --sd-color-tabs-underline-hover: #68d1ff; + --sd-color-tabs-underline: transparent; +} diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css new file mode 100644 index 00000000000..eb19f698afc --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css @@ -0,0 +1 @@ +.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative}details.sd-dropdown .sd-summary-title{font-weight:700;padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary{list-style:none;padding:1em}details.sd-dropdown summary .sd-octicon.no-title{vertical-align:middle}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown summary::-webkit-details-marker{display:none}details.sd-dropdown summary:focus{outline:none}details.sd-dropdown .sd-summary-icon{margin-right:.5em}details.sd-dropdown .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary:hover .sd-summary-up svg,details.sd-dropdown summary:hover .sd-summary-down svg{opacity:1;transform:scale(1.1)}details.sd-dropdown .sd-summary-up svg,details.sd-dropdown .sd-summary-down svg{display:block;opacity:.6}details.sd-dropdown .sd-summary-up,details.sd-dropdown .sd-summary-down{pointer-events:none;position:absolute;right:1em;top:1em}details.sd-dropdown[open]>.sd-summary-title .sd-summary-down{visibility:hidden}details.sd-dropdown:not([open])>.sd-summary-title .sd-summary-up{visibility:hidden}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #0071bc;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0060a0;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem} diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/design-tabs.js b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/design-tabs.js new file mode 100644 index 00000000000..36b38cf0d91 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/design-tabs.js @@ -0,0 +1,27 @@ +var sd_labels_by_text = {}; + +function ready() { + const li = document.getElementsByClassName("sd-tab-label"); + for (const label of li) { + syncId = label.getAttribute("data-sync-id"); + if (syncId) { + label.onclick = onLabelClick; + if (!sd_labels_by_text[syncId]) { + sd_labels_by_text[syncId] = []; + } + sd_labels_by_text[syncId].push(label); + } + } +} + +function onLabelClick() { + // Activate other inputs with the same sync id. + syncId = this.getAttribute("data-sync-id"); + for (label of sd_labels_by_text[syncId]) { + if (label === this) continue; + label.previousElementSibling.checked = true; + } + window.localStorage.setItem("sphinx-design-last-tab", syncId); +} + +document.addEventListener("DOMContentLoaded", ready, false); diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/doctools.js b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/doctools.js new file mode 100644 index 00000000000..527b876ca63 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/documentation_options.js b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/documentation_options.js new file mode 100644 index 00000000000..29d20387d8a --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/documentation_options.js @@ -0,0 +1,14 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '8.1.1', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/file.png b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 GIT binary patch literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( literal 0 HcmV?d00001 diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/graphviz.css b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/graphviz.css new file mode 100644 index 00000000000..19e7afd385b --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/graphviz.css @@ -0,0 +1,19 @@ +/* + * graphviz.css + * ~~~~~~~~~~~~ + * + * Sphinx stylesheet -- graphviz extension. + * + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +img.graphviz { + border: 0; + max-width: 100%; +} + +object.graphviz { + max-width: 100%; +} diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/jquery-3.6.0.js b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/jquery-3.6.0.js new file mode 100644 index 00000000000..fc6c299b73e --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/_static/jquery-3.6.0.js @@ -0,0 +1,10881 @@ +/*! + * jQuery JavaScript Library v3.6.0 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2021-03-02T17:08Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5 + // Plus for old WebKit, typeof returns "function" for HTML collections + // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756) + return typeof obj === "function" && typeof obj.nodeType !== "number" && + typeof obj.item !== "function"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.6.0", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), + function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); + } ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.6 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2021-02-16 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem && elem.namespaceURI, + docElem = elem && ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +} +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the primary Deferred + primary = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + primary.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( primary.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return primary.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject ); + } + + return primary.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + + // Support: Chrome 86+ + // In Chrome, if an element having a focusout handler is blurred by + // clicking outside of it, it invokes the handler synchronously. If + // that handler calls `.remove()` on the element, the data is cleared, + // leaving `result` undefined. We need to guard against this. + return result && result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + which: true +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + // Suppress native focus or blur as it's already being fired + // in leverageNative. + _default: function() { + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + // + // Support: Firefox 70+ + // Only Firefox includes border widths + // in computed dimensions. (gh-4529) + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate"; + tr.style.cssText = "border:1px solid"; + + // Support: Chrome 86+ + // Height set through cssText does not get applied. + // Computed height then comes back as 0. + tr.style.height = "1px"; + trChild.style.height = "9px"; + + // Support: Android 8 Chrome 86+ + // In our bodyBackground.html iframe, + // display for all div elements is set to "inline", + // which causes a problem only in Android 8 Chrome 86. + // Ensuring the div is display: block + // gets around this issue. + trChild.style.display = "block"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) + + parseInt( trStyle.borderTopWidth, 10 ) + + parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml, parserErrorElem; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) {} + + parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ]; + if ( !xml || parserErrorElem ) { + jQuery.error( "Invalid XML: " + ( + parserErrorElem ? + jQuery.map( parserErrorElem.childNodes, function( el ) { + return el.textContent; + } ).join( "\n" ) : + data + ) ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ).filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ).map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + +originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script but not if jsonp + if ( !isSuccess && + jQuery.inArray( "script", s.dataTypes ) > -1 && + jQuery.inArray( "json", s.dataTypes ) < 0 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+
+

apache-airflow-providers-cncf-kubernetes

+
+

Changelog

+
+

8.1.1

+
+

Bug Fixes

+
    +
  • Avoid logging empty line KPO (#38247)

  • +
+
+
+
+

8.1.0

+
+

Features

+
    +
  • KPO Add follow log in termination step (#38081)

  • +
  • Add GKECreateCustomResourceOperator and GKEDeleteCustomResourceOperator operators (#37616)

  • +
  • Implement deferrable mode for KubernetesJobOperator (#38251)

  • +
  • Create KubernetesPatchJobOperator operator (#38146)

  • +
  • Implement delete_on_status parameter for KubernetesDeleteJobOperator (#38458)

  • +
  • Implement deferrable mode for GKEStartJobOperator (#38454)

  • +
  • Use startup_check_interval_seconds instead of poll_interval to check pod while startup (#38075)

  • +
  • Implement wait_until_job_complete parameter for KubernetesJobOperator (#37998)

  • +
+
+
+

Bug Fixes

+
    +
  • Use SIGINT signal number instead of signal name (#37905)

  • +
  • Fix spark operator log retrieval from driver (#38106)

  • +
  • Fix dynamic allocation specs handling for custom launcher (#38223)

  • +
  • Fix case if 'SparkKubernetesOperator.application_file' is templated file (#38035)

  • +
  • fix: reduce irrelevant error logs for pod events. (#37944)

  • +
+
+
+

Misc

+
    +
  • Add GKEListJobsOperator and GKEDescribeJobOperator (#37598)

  • +
  • removed usage of deprecated function  for naming the pod in provider k8s pod.py (#38638)

  • +
  • Create DeleteKubernetesJobOperator and GKEDeleteJobOperator operators (#37793)

  • +
  • Refactor GKE hooks (#38404)

  • +
+
+
+
+

8.0.1

+
+

Bug Fixes

+
    +
  • Immediately fail the task in case of worker pod having a fatal container state (#37670)

  • +
  • Skip pod cleanup in case of pod creation failed (#37671)

  • +
+
+
+

Misc

+
    +
  • Avoid non-recommended usage of logging (#37792)

  • +
  • Migrate executor docs to respective providers (#37728)

  • +
+
+
+
+

8.0.0

+
+

Breaking changes

+

In the case of Kube API exceeded quota errors, we have introduced the task_publish_max_retries +flag to control the re-queuing task behavior. Changed the default behavior from unlimited +retries to 0. The default behavior is no retries (task_publish_max_retries==0). For +unlimited retries, set task_publish_max_retries=-1. For a fixed number of retries, set +task_publish_max_retries to any positive integer.

+
    +
  • Fix: The task is stuck in a queued state forever in case of pod launch errors (#36882)

  • +
+
+
+

Features

+
    +
  • Add logging_interval in KubernetesPodOperator to log container log periodically (#37279)

  • +
  • Create GKEStartJobOperator and KubernetesJobOperator (#36847)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix occasional attr-undefined for the python_kubernetes_script (#37318)

  • +
  • Fix hanging KPO on deferrable task with do_xcom_push (#37300)

  • +
  • Fix rendering 'SparkKubernetesOperator.template_body' (#37271)

  • +
  • Fix assignment of template field in '__init__' in 'KubernetesPodOperator' (#37010)

  • +
  • KPO Maintain backward compatibility for execute_complete and trigger run method (#37454)

  • +
  • Fix KPO task hanging when pod fails to start within specified timeout (#37514)

  • +
  • Fix KeyError when KPO exits too soon (#37508)

  • +
+
+
+

Misc

+
    +
  • feat: Switch all class, functions, methods deprecations to decorators (#36876)

  • +
  • Kubernetes version bump (#37040)

  • +
  • Add GKEStartKueueInsideClusterOperator (#37072)

  • +
  • Convert Kubernetes ApiException status code to string to ensure it's correctly checked (#37405)

  • +
+
+
+
+

7.14.0

+
+

Features

+
    +
  • Add SparkKubernetesOperator crd implementation (#22253)

  • +
  • Template field support for configmaps in the KubernetesPodOperator (#36922)

  • +
  • Create a generic callbacks class for KubernetesPodOperator (#35714)

  • +
+
+
+

Bug Fixes

+
    +
  • fix: Avoid retrying after KubernetesPodOperator has been marked as failed (#36749)

  • +
  • Fix stacklevel in warnings.warn into the providers (#36831)

  • +
  • Increase tenacity wait in read_pod_logs (#36955)

  • +
  • 36888-Fix k8 configmap issue in 7.14.0rc1 (#37001)

  • +
+
+
+

Misc

+
    +
  • Change field type for kube_config (#36752)

  • +
  • Changing wording in docstring for CNCF provider (#36547)

  • +
  • Add support of Pendulum 3 (#36281)

  • +
+
+
+
+

7.13.0

+
+

Features

+
    +
  • Allow changing of 'config_file' in 'KubernetesResourceBaseOperator' (#36397)

  • +
+
+
+

Misc

+
    +
  • Add reminder about update stub file in case of change KubernetesPodOperator's arguments (#36434)

  • +
  • Don't get pod status in KubernetesPodOperator if skip_on_exit_code is not set (#36355)

  • +
  • Remove deprecated input parameters in the k8s pod operator (#36433)

  • +
  • Delete get_python_source from Kubernetes decorator after bumping min airflow version to 2.6.0 (#36426)

  • +
  • Remove duplicated methods in K8S pod operator module and import them from helper function (#36427)

  • +
+
+
+
+

7.12.0

+
+

Features

+
    +
  • Add _request_timeout to KPO log fetch calls (#36297)

  • +
  • Add 'pod_template_dict' field to 'KubernetesPodOperator' (#33174)

  • +
  • KubernetesPodTrigger: add exception stack trace in TriggerEvent (#35716)

  • +
  • Make pod_name length equal to HOST_NAME_MAX (#36332)

  • +
  • Move KubernetesPodTrigger hook to a cached property (#36290)

  • +
+
+
+

Bug Fixes

+
    +
  • Kubernetes executor running slots leak fix (#36240)

  • +
  • Follow BaseHook connection fields method signature in child classes (#36086)

  • +
  • list pods performance optimization (#36092)

  • +
+
+
+
+

7.11.0

+
+

Note

+

This release of provider is only available for Airflow 2.6+ as explained in the +Apache Airflow providers support policy.

+
+
+

Bug Fixes

+
    +
  • fix: KPO typing env_vars (#36048)

  • +
  • Stop converting state to TaskInstanceState when it's None (#35891)

  • +
  • Feature pass dictionary configuration in application_file in SparkKubernetesOperator (#35848)

  • +
+
+
+

Misc

+
    +
  • Bump minimum Airflow version in providers to Airflow 2.6.0 (#36017)

  • +
+
+
+
+

7.10.0

+
+

Features

+
    +
  • Add annotations field into  in KubernetesPodOperator (#35641)

  • +
  • Add custom_resource_definition to KubernetesResourceBaseOperator (#35600)

  • +
+
+
+

Bug Fixes

+
    +
  • Revert Remove PodLoggingStatus object #35422 (#35822)

  • +
  • Fix K8S executor override config using pod_override_object (#35185)

  • +
  • Fix and reapply templates for provider documentation (#35686)

  • +
+
+
+

Misc

+
    +
  • Remove inconsequential code bits in KPO logging (#35416)

  • +
  • Remove non existing params from 'KubernetesResourceBaseOperator' docstring

  • +
  • KubernetesExecutor observability Improvements (#35579)

  • +
+
+
+
+

7.9.0

+
+

Features

+
    +
  • Add verificationy that provider docs are as expected (#35424)

  • +
  • Add startup_check_interval_seconds to PodManager's await_pod_start (#34231)

  • +
+
+
+

Bug Fixes

+
    +
  • Remove before_log in KPO retry and add traceback when interrupted (#35423)

  • +
  • Remove tenancity on KPO logs inner func consume_logs (#35504)

  • +
+
+
+

Misc

+
    +
  • Simplify KPO multi container log reconciliation logic (#35450)

  • +
  • Remove PodLoggingStatus object (#35422)

  • +
  • Improve clear_not_launched_queued_tasks call duration (#34985)

  • +
  • Use constant for empty xcom result sentinel (#35451)

  • +
+
+
+
+

7.8.0

+
+

Features

+
    +
  • Added to the rendering of KubernetesOperator V1VolumeMount, sub_path (#35129)

  • +
  • feat: add hostAliases to pod spec in KubernetesPodOperator (#35063)

  • +
+
+
+

Bug Fixes

+
    +
  • Replace blocking IO with async IO in AsyncKubernetesHook (#35162)

  • +
  • Consolidate the warning stacklevel in KubernetesPodTrigger (#35079)

  • +
+
+
+
+

7.7.0

+
+

Note

+

This release of provider is only available for Airflow 2.5+ as explained in the +Apache Airflow providers support policy.

+
+
+

Bug Fixes

+
    +
  • Fix parsing KubernetesPodOperator multiline logs (#34412)

  • +
  • Fix KubernetesPodTrigger startup timeout (#34579)

  • +
  • Fix Pod not being removed after istio-sidecar is removed  (#34500)

  • +
  • Remove duplicated logs by reusing PodLogsConsumer (#34127)

  • +
+
+
+

Misc

+
    +
  • Bump min airflow version of providers (#34728)

  • +
  • warn level for deprecated set to stacklevel 2 (#34530)

  • +
  • Use 'airflow.exceptions.AirflowException' in providers (#34511)

  • +
+
+
+
+

7.6.0

+
+

Features

+
    +
  • Add 'progress_callback' parameter to 'KubernetesPodOperator' (#34153)

  • +
+
+
+

Bug Fixes

+
    +
  • Move definition of Pod*Exceptions to pod_generator (#34346)

  • +
  • Push to xcom before 'KubernetesPodOperator' deferral (#34209)

  • +
+
+
+

Misc

+
    +
  • Refactor: Consolidate import textwrap in providers (#34220)

  • +
+
+
+
+

7.5.1

+
+

Bug Fixes

+
    +
  • fix(providers/spark-kubernetes): respect soft_fail argument when exception is raised (#34167)

  • +
  • Use 'cached_property' for hook in SparkKubernetesSensor (#34106)

  • +
  • Use cached property for hook in SparkKubernetesOperator (#34130)

  • +
+
+
+

Misc

+
    +
  • Combine similar if logics in providers (#33987)

  • +
  • Remove useless string join from providers (#33968)

  • +
  • Refactor unneeded  jumps in providers (#33833)

  • +
  • replace loop by any when looking for a positive value in providers (#33984)

  • +
  • Move the try outside the loop when this is possible in kubernetes provider (#33977)

  • +
  • Replace sequence concatenation by unpacking in Airflow providers (#33933)

  • +
  • Replace dict.items by values when key is not used in providers (#33939)

  • +
  • Refactor: Consolidate import datetime (#34110)

  • +
+
+
+
+

7.5.0

+
+

Features

+
    +
  • Add istio test, use curl /quitquitquit to exit sidecar, and some othe… (#33306)

  • +
  • Add 'active_deadline_seconds' parameter to 'KubernetesPodOperator' (#33379)

  • +
  • Make cluster_context templated (#33604)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix KubernetesPodOperator duplicating logs when interrupted (#33500)

  • +
  • Fix 2.7.0 db migration job errors (#33652)

  • +
  • Inspect container state rather than last_state when deciding whether to skip (#33702)

  • +
  • Fix kill istio proxy logic (#33779)

  • +
+
+
+

Misc

+
    +
  • Introducing class constant to make worker pod log lines configurable (#33378)

  • +
  • Adding typing for KPO SCC objects (#33381)

  • +
  • Refactor: Remove useless str() calls (#33629)

  • +
  • Refactor: Improve detection of duplicates and list sorting (#33675)

  • +
  • Refactor Sqlalchemy queries to 2.0 style (Part 7) (#32883)

  • +
  • Consolidate import and usage of itertools (#33479)

  • +
  • Simplify conditions on len() in other providers (#33569)

  • +
  • Import utc from datetime and normalize its import (#33450)

  • +
  • Always use 'Literal' from 'typing_extensions' (#33794)

  • +
  • Use literal dict instead of calling dict() in providers (#33761)

  • +
  • Improve modules import in cncf.kubernetes probvider by move some of them into a type-checking block (#33781)

  • +
+
+
+
+

7.4.2

+
+

Misc

+
    +
  • Add missing re2 dependency to cncf.kubernetes and celery providers (#33237)

  • +
  • Make the 'OnFinishAction' enum inherit from str to support passing it to 'KubernetesPodOperatpor' (#33228)

  • +
  • Refactor: Simplify code in providers/cncf (#33230)

  • +
  • Replace State by TaskInstanceState in Airflow executors (#32627)

  • +
+
+
+
+

7.4.1

+
+

Bug Fixes

+
    +
  • Fix waiting the base container when reading the logs of other containers (#33127)

  • +
  • Fix: Configurable Docker image of 'xcom_sidecar' (#32858)

  • +
  • Fix 'KubernetesPodOperator' sub classes default container_logs (#33090)

  • +
  • Consider custom pod labels on pod finding process on 'KubernetesPodOperator' (#33057)

  • +
+
+
+

Misc

+
    +
  • add documentation generation for CLI commands from executors (#33081)

  • +
+
+
+
+

7.4.0

+
+

Note

+

This provider release is the first release that has Kubernetes Executor and +Local Kubernetes Executor moved from the core apache-airflow package to the cncf.kubernetes +provider package.

+
+
+

Features

+
    +
  • Move all k8S classes to cncf.kubernetes provider (#32767)

  • +
  • [AIP-51] Executors vending CLI commands (#29055)

  • +
  • Add 'termination_message_policy' parameter to 'KubernetesPodOperator' (#32885)

  • +
+
+
+

Misc

+
    +
  • Update the watcher resource version in SparkK8SOp when it's too old (#32768)

  • +
  • Add deprecation info to the providers modules and classes docstring (#32536)

  • +
  • Raise original import error in CLI vending of executors (#32931)

  • +
+
+
+
+

7.3.0

+
+

Features

+
    +
  • Logging from all containers in KubernetesOperatorPod (#31663)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix async KPO by waiting pod termination in 'execute_complete' before cleanup (#32467)

  • +
+
+
+
+

7.2.0

+
+

Features

+
    +
  • Add 'on_finish_action' to 'KubernetesPodOperator' (#30718)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix KubernetesPodOperator validate xcom json and add retries (#32113)

  • +
  • Fix 'KubernetesPodTrigger' waiting strategy (#31348)

  • +
  • fix spark-kubernetes-operator compatibality (#31798)

  • +
+
+
+

Misc

+
    +
  • Add default_deferrable config (#31712)

  • +
+
+
+
+

7.1.0

+
+

Note

+

This release dropped support for Python 3.7

+
+
+

Features

+
    +
  • KubernetesResourceOperator - KubernetesDeleteResourceOperator & KubernetesCreateResourceOperator (#29930)

  • +
  • add a return when the event is yielded in a loop to stop the execution (#31985)

  • +
  • Add possibility to disable logging the pod template in a case when task fails (#31595)

  • +
+
+
+

Bug Fixes

+
    +
  • Remove return statement after yield from triggers class (#31703)

  • +
  • Fix Fargate logging for AWS system tests (#31622)

  • +
+
+
+

Misc

+
    +
  • Remove Python 3.7 support (#30963)

  • +
+
+
+
+

7.0.0

+
+

Note

+

This release of provider is only available for Airflow 2.4+ as explained in the +Apache Airflow providers support policy.

+
+
+

Breaking changes

+
+

Note

+

Return None when namespace is not defined in the Kubernetes connection

+
+
    +
  • Remove deprecated features from KubernetesHook (#31402)

  • +
+
+
+

Features

+
+

Note

+

If kubernetes_default connection is not defined, then KubernetesHook / KubernetesPodOperator will behave as though given conn_id=None. +This should make it easier to mitigate breaking change introduced in 6.0.0

+
+
    +
  • K8s hook should still work with missing default conn (#31187)

  • +
  • Add protocol to define methods relied upon by KubernetesPodOperator (#31298)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix kubernetes task decorator pickle error (#31110)

  • +
+
+
+

Misc

+
    +
  • Bump minimum Airflow version in providers (#30917)

  • +
  • Empty xcom result file log message more specific (#31228)

  • +
  • Add options to KubernetesPodOperator (#30992)

  • +
  • add missing read for K8S config file from conn in deferred 'KubernetesPodOperator'  (#29498)

  • +
+
+
+
+

6.1.0

+
+

Features

+
    +
  • Add multiple exit code handling in skip logic for 'DockerOperator' and 'KubernetesPodOperator' (#30769)

  • +
  • Skip KubernetesPodOperator task when it returns a provided exit code (#29000)

  • +
+
+
+
+

6.0.0

+
+

Breaking changes

+

Use kubernetes_default connection by default in the KubernetesPodOperator.

+
    +
  • Use default connection id for KubernetesPodOperator (#28848)

  • +
+
+
+

Features

+
    +
  • Allow to set limits for XCOM container (#28125)

  • +
+
+
+
+

5.3.0

+
+

Features

+
    +
  • enhance spark_k8s_operator (#29977)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix KubernetesPodOperator xcom push when 'get_logs=False' (#29052)

  • +
  • Fixed hanged KubernetesPodOperator (#28336)

  • +
+
+
+

Misc

+
    +
  • Align cncf provider file names with AIP-21 (#29905)

  • +
  • Remove "boilerplate" from all taskflow decorators (#30118)

  • +
  • Ensure setup/teardown work on a previously decorated function (#30216)

  • +
+
+
+
+

5.2.2

+
+

Bug Fixes

+
    +
  • 'KubernetesPodOperator._render_nested_template_fields' improved by changing the conditionals for a map (#29760)

  • +
+
+
+
+

5.2.1

+
+

Bug Fixes

+
    +
  • Fix @task.kubernetes to receive input and send output (#28942)

  • +
+
+
+
+

5.2.0

+
+

Features

+
    +
  • Add deferrable mode to ''KubernetesPodOperator'' (#29017)

  • +
  • Allow setting the name for the base container within K8s Pod Operator (#28808)

  • +
+
+
+

Bug Fixes

+
    +
  • Patch only single label when marking KPO checked (#29279)

  • +
+
+
+
+

5.1.1

+
+

Bug Fixes

+
    +
  • Fix Incorrect 'await_container_completion' (#28771)

  • +
+
+
+
+

5.1.0

+
+

Features

+
    +
  • Add Flink on K8s Operator  (#28512)

  • +
  • Add volume-related nested template fields for KPO (#27719)

  • +
  • Allow longer pod names for k8s executor / KPO (#27736)

  • +
  • Use labels instead of pod name for pod log read in k8s exec (#28546)

  • +
+
+
+

Bug Fixes

+
    +
  • Patch "checked" when pod not successful (#27845)

  • +
  • Keep pod name for k8s executor under 63 characters (#28237)

  • +
+
+
+

Misc

+
    +
  • Remove outdated compat imports/code from providers (#28507)

  • +
  • Restructure Docs  (#27235)

  • +
+
+
+
+

5.0.0

+
+

Note

+

This release of provider is only available for Airflow 2.3+ as explained in the +Apache Airflow providers support policy.

+
+
+

Breaking changes

+

Previously KubernetesPodOperator considered some settings from the Airflow config’s kubernetes section. +Such consideration was deprecated in 4.1.0 and is now removed. If you previously relied on the Airflow +config, and you want client generation to have non-default configuration, you will need to define your +configuration in an Airflow connection and set KPO to use the connection. See kubernetes provider +documentation on defining a kubernetes Airflow connection for details.

+

Drop support for providing resource as dict in KubernetesPodOperator. You +should use container_resources with V1ResourceRequirements.

+

Param node_selectors has been removed in KubernetesPodOperator; use node_selector instead.

+

The following backcompat modules for KubernetesPodOperator are removed and you must now use +the corresponding objects from the kubernetes library:

+
    +
  • airflow.kubernetes.backcompat.pod

  • +
  • airflow.kubernetes.backcompat.pod_runtime_info_env

  • +
  • airflow.kubernetes.backcompat.volume

  • +
  • airflow.kubernetes.backcompat.volume_mount

  • +
  • Remove deprecated backcompat objects for KPO (#27518)

  • +
  • Remove support for node_selectors param in KPO (#27515)

  • +
  • Remove unused backcompat method in k8s hook (#27490)

  • +
  • Drop support for providing ''resource'' as dict in ''KubernetesPodOperator'' (#27197)

  • +
  • Don't consider airflow core conf for KPO (#26849)

  • +
+
+
+

Misc

+
    +
  • Move min airflow version to 2.3.0 for all providers (#27196)

  • +
  • Use log.exception where more economical than log.error (#27517)

  • +
+
+
+

Features

+

KubernetesPodOperator argument name is now optional. Previously, name was a +required argument for KubernetesPodOperator when also not supplying pod +template or full pod spec. Now, if name is not supplied, task_id will be used.

+

KubernetesPodOperator argument namespace is now optional. If not supplied via KPO param or pod +template file or full pod spec, then we’ll check the airflow conn, +then if in a k8s pod, try to infer the namespace from the container, then finally +will use the default namespace.

+

When using an Airflow connection of type kubernetes, if defining the connection in an env var +or secrets backend, it’s no longer necessary to prefix the “extra” fields with extra__kubernetes__. +If extra contains duplicate fields (one with prefix, one without) then the non-prefixed +one will be used.

+
    +
  • Remove extra__kubernetes__ prefix from k8s hook extras (#27021)

  • +
  • Add container_resources as KubernetesPodOperator templatable (#27457)

  • +
  • add container_name option for SparkKubernetesSensor (#26560)

  • +
  • Allow xcom sidecar container image to be configurable in KPO (#26766)

  • +
  • Improve task_id to pod name conversion (#27524)

  • +
  • Make pod name optional in KubernetesPodOperator (#27120)

  • +
  • Make namespace optional for KPO (#27116)

  • +
  • Enable template rendering for env_vars field for the @task.kubernetes decorator (#27433)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix KubernetesHook fail on an attribute absence (#25787)

  • +
  • Fix log message for kubernetes hooks (#26999)

  • +
  • KPO should use hook's get namespace method to get namespace (#27516)

  • +
+
+
+

New deprecations

+
    +
  • +
    In KubernetesHook.get_namespace, if a connection is defined but a namespace isn’t set, we

    currently return ‘default’; this behavior is deprecated (#27202). In the next release, we’ll return None.

    +
    +
    +
  • +
  • Deprecate use of core get_kube_client in PodManager (#26848)

  • +
+
+
+
+

4.4.0

+
+

Features

+
    +
  • feat(KubernetesPodOperator): Add support of container_security_context (#25530)

  • +
  • Add @task.kubernetes taskflow decorator (#25663)

  • +
  • pretty print KubernetesPodOperator rendered template env_vars (#25850)

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid calculating all elements when one item is needed (#26377)

  • +
  • Wait for xcom sidecar container to start before sidecar exec (#25055)

  • +
+
+
+
+

4.3.0

+
+

Features

+
    +
  • Improve taskflow type hints with ParamSpec (#25173)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix xcom_sidecar stuck problem (#24993)

  • +
+
+
+
+

4.2.0

+
+

Features

+
    +
  • Add 'airflow_kpo_in_cluster' label to KPO pods (#24658)

  • +
  • Use found pod for deletion in KubernetesPodOperator (#22092)

  • +
+
+
+

Bug Fixes

+
    +
  • Revert "Fix await_container_completion condition (#23883)" (#24474)

  • +
  • Update providers to use functools compat for ''cached_property'' (#24582)

  • +
+
+
+

Misc

+
    +
  • Rename 'resources' arg in Kub op to k8s_resources (#24673)

  • +
+
+
+
+

4.1.0

+
+

Features

+
    +
  • Previously, KubernetesPodOperator relied on core Airflow configuration (namely setting for kubernetes +executor) for certain settings used in client generation. Now KubernetesPodOperator +uses KubernetesHook, and the consideration of core k8s settings is officially deprecated.

  • +
  • If you are using the Airflow configuration settings (e.g. as opposed to operator params) to +configure the kubernetes client, then prior to the next major release you will need to +add an Airflow connection and set your KPO tasks to use that connection.

  • +
  • Use KubernetesHook to create api client in KubernetesPodOperator (#20578)

  • +
  • [FEATURE] KPO use K8S hook (#22086)

  • +
  • Add param docs to KubernetesHook and KubernetesPodOperator (#23955) (#24054)

  • +
+
+
+

Bug Fixes

+
    +
  • Use "remote" pod when patching KPO pod as "checked" (#23676)

  • +
  • Don't use the root logger in KPO _suppress function (#23835)

  • +
  • Fix await_container_completion condition (#23883)

  • +
+
+
+

Misc

+
    +
  • Migrate Cncf.Kubernetes example DAGs to new design #22441 (#24132)

  • +
  • Clean up f-strings in logging calls (#23597)

  • +
+
+
+
+

4.0.2

+
+

Bug Fixes

+
    +
  • Fix: Exception when parsing log #20966 (#23301)

  • +
  • Fixed Kubernetes Operator large xcom content Defect  (#23490)

  • +
  • Clarify 'reattach_on_restart' behavior (#23377)

  • +
+
+
+
+

4.0.1

+
+

Bug Fixes

+
    +
  • Add k8s container's error message in airflow exception (#22871)

  • +
  • KubernetesHook should try incluster first when not otherwise configured (#23126)

  • +
  • KubernetesPodOperator should patch "already checked" always (#22734)

  • +
  • Delete old Spark Application in SparkKubernetesOperator (#21092)

  • +
  • Cleanup dup code now that k8s provider requires 2.3.0+ (#22845)

  • +
  • Fix ''KubernetesPodOperator'' with 'KubernetesExecutor'' on 2.3.0 (#23371)

  • +
  • Fix KPO to have hyphen instead of period (#22982)

  • +
  • Fix new MyPy errors in main (#22884)

  • +
+
+
+
+

4.0.0

+
+

Breaking changes

+

The provider in version 4.0.0 only works with Airflow 2.3+. Please upgrade +Airflow to 2.3 version if you want to use the features or fixes in 4.* line +of the provider.

+

The main reason for the incompatibility is using latest Kubernetes Libraries. +The cncf.kubernetes provider requires newer version of libraries than +Airflow 2.1 and 2.2 used for Kubernetes Executor and that makes the provider +incompatible with those Airflow versions.

+
+
+

Features

+
    +
  • Log traceback only on ''DEBUG'' for KPO logs read interruption (#22595)

  • +
  • Update our approach for executor-bound dependencies (#22573)

  • +
  • Optionally not follow logs in KPO pod_manager (#22412)

  • +
+
+
+

Bug Fixes

+
    +
  • Stop crashing when empty logs are received from kubernetes client (#22566)

  • +
+
+
+
+

3.1.2 (YANKED)

+
+

Warning

+

This release has been yanked with a reason: Installing on Airflow 2.1, 2.2 allows to install unsupported kubernetes library > 11.0.0

+
+
+

Bug Fixes

+
    +
  • Fix mistakenly added install_requires for all providers (#22382)

  • +
  • Fix "run_id" k8s and elasticsearch compatibility with Airflow 2.1 (#22385)

  • +
+
+
+

Misc

+
    +
  • Remove RefreshConfiguration workaround for K8s token refreshing (#20759)

  • +
+
+
+
+

3.1.1 (YANKED)

+
+

Warning

+

This release has been yanked with a reason: Installing on Airflow 2.1, 2.2 allows to install unsupported kubernetes library > 11.0.0

+
+
+

Misc

+
    +
  • Add Trove classifiers in PyPI (Framework :: Apache Airflow :: Provider)

  • +
+
+
+
+

3.1.0 (YANKED)

+
+

Warning

+

This release has been yanked with a reason: Installing on Airflow 2.1, 2.2 allows to install unsupported kubernetes library > 11.0.0

+
+
+

Features

+
    +
  • Add map_index label to mapped KubernetesPodOperator (#21916)

  • +
  • Change KubernetesPodOperator labels from execution_date to run_id (#21960)

  • +
+
+
+

Misc

+
    +
  • Support for Python 3.10

  • +
  • Fix Kubernetes example with wrong operator casing (#21898)

  • +
  • Remove types from KPO docstring (#21826)

  • +
+
+
+
+

3.0.2 (YANKED)

+
+

Warning

+

This release has been yanked with a reason: Installing on Airflow 2.1, 2.2 allows to install unsupported kubernetes library > 11.0.0

+
+
+

Bug Fixes

+
    +
  • Add missed deprecations for cncf (#20031)

  • +
+
+
+
+

3.0.1 (YANKED)

+
+

Warning

+

This release has been yanked with a reason: Installing on Airflow 2.1, 2.2 allows to install unsupported kubernetes library > 11.0.0

+
+
+

Misc

+
    +
  • Update Kubernetes library version (#18797)

  • +
+
+
+
+

3.0.0

+
+

Breaking changes

+
    +
  • Parameter is_delete_operator_pod default is changed to True (#20575)

  • +
  • Simplify KubernetesPodOperator (#19572)

  • +
  • Move pod_mutation_hook call from PodManager to KubernetesPodOperator (#20596)

  • +
  • Rename ''PodLauncher'' to ''PodManager'' (#20576)

  • +
+
+

Parameter is_delete_operator_pod has new default

+

Previously, the default for param is_delete_operator_pod was False, which means that +after a task runs, its pod is not deleted by the operator and remains on the +cluster indefinitely. With this release, we change the default to True.

+
+
+

Notes on changes KubernetesPodOperator and PodLauncher

+
+

Warning

+

Many methods in KubernetesPodOperator and PodLauncher have been renamed. +If you have subclassed KubernetesPodOperator you will need to update your subclass to reflect +the new structure. Additionally PodStatus enum has been renamed to PodPhase.

+
+
+
Overview
+

Generally speaking if you did not subclass KubernetesPodOperator and you did not use the PodLauncher class directly, +then you don’t need to worry about this change. If however you have subclassed KubernetesPodOperator, what +follows are some notes on the changes in this release.

+

One of the principal goals of the refactor is to clearly separate the “get or create pod” and +“wait for pod completion” phases. Previously the “wait for pod completion” logic would be invoked +differently depending on whether the operator were to “attach to an existing pod” (e.g. after a +worker failure) or “create a new pod” and this resulted in some code duplication and a bit more +nesting of logic. With this refactor we encapsulate the “get or create” step +into method KubernetesPodOperator.get_or_create_pod, and pull the monitoring and XCom logic up +into the top level of execute because it can be the same for “attached” pods and “new” pods.

+

The KubernetesPodOperator.get_or_create_pod tries first to find an existing pod using labels +specific to the task instance (see KubernetesPodOperator.find_pod). +If one does not exist it creates a pod <~.PodManager.create_pod>.

+

The “waiting” part of execution has three components. The first step is to wait for the pod to leave the +Pending phase (~.KubernetesPodOperator.await_pod_start). Next, if configured to do so, +the operator will follow the base container logs and forward these logs to the task logger until +the base container is done. If not configured to harvest the +logs, the operator will instead KubernetesPodOperator.await_container_completion +either way, we must await container completion before harvesting xcom. After (optionally) extracting the xcom +value from the base container, we await pod completion <~.PodManager.await_pod_completion>.

+

Previously, depending on whether the pod was “reattached to” (e.g. after a worker failure) or +created anew, the waiting logic may have occurred in either handle_pod_overlap or create_new_pod_for_operator.

+

After the pod terminates, we execute different cleanup tasks depending on whether the pod terminated successfully.

+

If the pod terminates unsuccessfully, we attempt to log the pod events PodLauncher.read_pod_events>. If +additionally the task is configured not to delete the pod after termination, we apply a label KubernetesPodOperator.patch_already_checked> +indicating that the pod failed and should not be “reattached to” in a retry. If the task is configured +to delete its pod, we delete it KubernetesPodOperator.process_pod_deletion>. Finally, +we raise an AirflowException to fail the task instance.

+

If the pod terminates successfully, we delete the pod KubernetesPodOperator.process_pod_deletion> +(if configured to delete the pod) and push XCom (if configured to push XCom).

+
+
+
Details on method renames, refactors, and deletions
+

In KubernetesPodOperator:

+
    +
  • Method create_pod_launcher is converted to cached property pod_manager

  • +
  • Construction of k8s CoreV1Api client is now encapsulated within cached property client

  • +
  • Logic to search for an existing pod (e.g. after an airflow worker failure) is moved out of execute and into method find_pod.

  • +
  • Method handle_pod_overlap is removed. Previously it monitored a “found” pod until completion. With this change the pod monitoring (and log following) is orchestrated directly from execute and it is the same whether it’s a “found” pod or a “new” pod. See methods await_pod_start, follow_container_logs, await_container_completion and await_pod_completion.

  • +
  • Method create_pod_request_obj is renamed build_pod_request_obj. It now takes argument context in order to add TI-specific pod labels; previously they were added after return.

  • +
  • Method create_labels_for_pod is renamed _get_ti_pod_labels. This method doesn’t return all labels, but only those specific to the TI. We also add parameter include_try_number to control the inclusion of this label instead of possibly filtering it out later.

  • +
  • Method _get_pod_identifying_label_string is renamed _build_find_pod_label_selector

  • +
  • Method _try_numbers_match is removed.

  • +
  • Method create_new_pod_for_operator is removed. Previously it would mutate the labels on self.pod, launch the pod, monitor the pod to completion etc. Now this logic is in part handled by get_or_create_pod, where a new pod will be created if necessary. The monitoring etc is now orchestrated directly from execute. Again, see the calls to methods await_pod_start, follow_container_logs, await_container_completion and await_pod_completion.

  • +
+

In class PodManager (formerly PodLauncher):

+
    +
  • Method start_pod is removed and split into two methods: create_pod and await_pod_start.

  • +
  • Method monitor_pod is removed and split into methods follow_container_logs, await_container_completion, await_pod_completion

  • +
  • Methods pod_not_started, pod_is_running, process_status, and _task_status are removed. These were needed due to the way in which pod phase was mapped to task instance states; but we no longer do such a mapping and instead deal with pod phases directly and untransformed.

  • +
  • Method _extract_xcom is renamed extract_xcom.

  • +
  • Method read_pod_logs now takes kwarg container_name

  • +
+

Other changes in pod_manager.py (formerly pod_launcher.py):

+
    +
  • Class pod_launcher.PodLauncher renamed to pod_manager.PodManager

  • +
  • Enum-like class PodStatus is renamed PodPhase, and the values are no longer lower-cased.

  • +
  • The airflow.settings.pod_mutation_hook is no longer called in +cncf.kubernetes.utils.pod_manager.PodManager.run_pod_async. For KubernetesPodOperator, +mutation now occurs in build_pod_request_obj.

  • +
  • Parameter is_delete_operator_pod default is changed to True so that pods are deleted after task +completion and not left to accumulate. In practice it seems more common to disable pod deletion only on a +temporary basis for debugging purposes and therefore pod deletion is the more sensible default.

  • +
+
+
+
+
+

Features

+
    +
  • Add params config, in_cluster, and cluster_context to KubernetesHook (#19695)

  • +
  • Implement dry_run for KubernetesPodOperator (#20573)

  • +
  • Clarify docstring for ''build_pod_request_obj'' in K8s providers (#20574)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix Volume/VolumeMount KPO DeprecationWarning (#19726)

  • +
+
+
+
+

2.2.0

+
+

Features

+
    +
  • Added namespace as a template field in the KPO. (#19718)

  • +
  • Decouple name randomization from name kwarg (#19398)

  • +
+
+
+

Bug Fixes

+
    +
  • Checking event.status.container_statuses before filtering (#19713)

  • +
  • Coalesce 'extra' params to None in KubernetesHook (#19694)

  • +
  • Change to correct type in KubernetesPodOperator (#19459)

  • +
+
+
+
+

2.1.0

+
+

Features

+
    +
  • Add more type hints to PodLauncher (#18928)

  • +
  • Add more information to PodLauncher timeout error (#17953)

  • +
+
+
+
+

2.0.3

+
+

Bug Fixes

+
    +
  • Fix KubernetesPodOperator reattach when not deleting pods (#18070)

  • +
  • Make Kubernetes job description fit on one log line (#18377)

  • +
  • Do not fail KubernetesPodOperator tasks if log reading fails (#17649)

  • +
+
+
+
+

2.0.2

+
+

Bug Fixes

+
    +
  • Fix using XCom with ''KubernetesPodOperator'' (#17760)

  • +
  • Import Hooks lazily individually in providers manager (#17682)

  • +
+
+
+
+

2.0.1

+
+

Features

+
    +
  • Enable using custom pod launcher in Kubernetes Pod Operator (#16945)

  • +
+
+
+

Bug Fixes

+
    +
  • BugFix: Using 'json' string in template_field causes issue with K8s Operators (#16930)

  • +
+
+
+
+

2.0.0

+
+

Breaking changes

+
    +
  • Auto-apply apply_default decorator (#15667)

  • +
+
+

Warning

+

Due to apply_default decorator removal, this version of the provider requires Airflow 2.1.0+. +If your Airflow version is < 2.1.0, and you want to install this provider version, first upgrade +Airflow to at least version 2.1.0. Otherwise your Airflow package version will be upgraded +automatically and you will have to manually run airflow upgrade db to complete the migration.

+
+
+
+

Features

+
    +
  • Add 'KubernetesPodOperator' 'pod-template-file' jinja template support (#15942)

  • +
  • Save pod name to xcom for KubernetesPodOperator (#15755)

  • +
+
+
+

Bug Fixes

+
    +
  • Bug Fix Pod-Template Affinity Ignored due to empty Affinity K8S Object (#15787)

  • +
  • Bug Pod Template File Values Ignored (#16095)

  • +
  • Fix issue with parsing error logs in the KPO (#15638)

  • +
  • Fix unsuccessful KubernetesPodOperator final_state call when 'is_delete_operator_pod=True' (#15490)

  • +
+
+
+
+

1.2.0

+
+

Features

+
    +
  • Require 'name' with KubernetesPodOperator (#15373)

  • +
  • Change KPO node_selectors warning to proper deprecationwarning (#15507)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix timeout when using XCom with KubernetesPodOperator (#15388)

  • +
  • Fix labels on the pod created by ''KubernetesPodOperator'' (#15492)

  • +
+
+
+
+

1.1.0

+
+

Features

+
    +
  • Separate Kubernetes pod_launcher from core airflow (#15165)

  • +
  • Add ability to specify api group and version for Spark operators (#14898)

  • +
  • Use libyaml C library when available. (#14577)

  • +
+
+
+
+

1.0.2

+
+

Bug fixes

+
    +
  • Allow pod name override in KubernetesPodOperator if pod_template is used. (#14186)

  • +
  • Allow users of the KPO to *actually* template environment variables (#14083)

  • +
+
+
+
+

1.0.1

+

Updated documentation and readme files.

+
+

Bug fixes

+
    +
  • Pass image_pull_policy in KubernetesPodOperator correctly (#13289)

  • +
+
+
+
+

1.0.0

+

Initial version of the provider.

+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/cli-ref.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/cli-ref.html new file mode 100644 index 00000000000..8e73494ba84 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/cli-ref.html @@ -0,0 +1,1012 @@ + + + + + + + + + + + + Kubernetes Executor Commands — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

Kubernetes Executor Commands

+
+

Note

+

The CLI commands below are used from provider by Airflow 2.7.0+. +Previously they were part of the core Airflow, so if you are using Airflow below 2.7.0 look at +the core Airflow documentation for the list of CLI commands and parameters available.

+
+
Usage: airflow [-h] GROUP_OR_COMMAND ...
+
+
+
+

Positional Arguments

+
+
GROUP_OR_COMMAND
+

Possible choices: kubernetes

+
+
+
+
+

Sub-commands

+
+

kubernetes

+

Tools to help run the KubernetesExecutor

+
airflow kubernetes [-h] COMMAND ...
+
+
+
+

Positional Arguments

+
+
COMMAND
+

Possible choices: cleanup-pods, generate-dag-yaml

+
+
+
+
+

Sub-commands

+
+
cleanup-pods
+

Clean up Kubernetes pods (created by KubernetesExecutor/KubernetesPodOperator) in evicted/failed/succeeded/pending states

+
airflow kubernetes cleanup-pods [-h]
+                                [--min-pending-minutes MIN_PENDING_MINUTES]
+                                [--namespace NAMESPACE] [-v]
+
+
+
+
Named Arguments
+
+
--min-pending-minutes
+

Pending pods created before the time interval are to be cleaned up, measured in minutes. Default value is 30(m). The minimum value is 5(m).

+

Default: 30

+
+
--namespace
+

Kubernetes Namespace. Default value is [kubernetes] namespace in configuration.

+

Default: “default”

+
+
-v, --verbose
+

Make logging output more verbose

+

Default: False

+
+
+
+
+
+
generate-dag-yaml
+

Generate YAML files for all tasks in DAG. Useful for debugging tasks without launching into a cluster

+
airflow kubernetes generate-dag-yaml [-h] [-o OUTPUT_PATH] [-S SUBDIR] [-v]
+                                     dag_id execution_date
+
+
+
+
Positional Arguments
+
+
dag_id
+

The id of the dag

+
+
execution_date
+

The execution date of the DAG

+
+
+
+
+
Named Arguments
+
+
-o, --output-path
+

The output for generated yaml files

+

Default: “[CWD]”

+
+
-S, --subdir
+

File location or directory from which to look for the dag. Defaults to ‘[AIRFLOW_HOME]/dags’ where [AIRFLOW_HOME] is the value you set for ‘AIRFLOW_HOME’ config you set in ‘airflow.cfg’

+

Default: “[AIRFLOW_HOME]/dags”

+
+
-v, --verbose
+

Make logging output more verbose

+

Default: False

+
+
+
+
+
+
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/commits.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/commits.html new file mode 100644 index 00000000000..9d9843fab88 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/commits.html @@ -0,0 +1,4211 @@ + + + + + + + + + + + + Package apache-airflow-providers-cncf-kubernetes — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

Package apache-airflow-providers-cncf-kubernetes

+

Kubernetes

+

This is detailed commit list of changes for versions provider package: cncf.kubernetes. +For high-level changelog, see package information including changelog.

+
+

8.1.1

+

Latest change: 2024-04-15

+ +++++ + + + + + + + + + + + + +

Commit

Committed

Subject

43919c2fa6

2024-04-15

Avoid logging empty line KPO (#38247)

+
+
+

8.1.0

+

Latest change: 2024-04-10

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

5fa80b6aea

2024-04-10

Prepare docs 1st wave (RC1) April 2024 (#38863)

78f84b9147

2024-04-09

fix: try002 for provider cncf kubernetes (#38799)

a19a9cb523

2024-04-05

removed usage of deprecated function  for naming the pod in provider k8s pod.py (#38638)

ab5aabe50b

2024-04-02

Implement delete_on_status parameter for KubernetesDeleteJobOperator (#38458)

ec6091d498

2024-03-31

Fix spark operator log retrieval from driver (#38106)

afb686c95e

2024-03-26

Implement deferrable mode for GKEStartJobOperator (#38454)

a3f7ddd465

2024-03-26

KPO Add follow log in termination step (#38081)

32ed83bd0e

2024-03-25

Refactor GKE hooks (#38404)

fc868f4be2

2024-03-22

Implement deferrable mode for KubernetesJobOperator (#38251)

1a9b71a129

2024-03-21

Create KubernetesPatchJobOperator operator (#38146)

29ac05f496

2024-03-18

Create DeleteKubernetesJobOperator and GKEDeleteJobOperator operators (#37793)

b5b972a106

2024-03-18

Update yanked versions in providers changelogs (#38262)

d4350a6bed

2024-03-18

Fix dynamic allocation specs handling for custom launcher (#38223)

0a74928894

2024-03-18

Bump ruff to 0.3.3 (#38240)

f3982aa2a4

2024-03-18

Use startup_check_interval_seconds instead of poll_interval to check pod while startup (#38075)

c32d41d94d

2024-03-18

Implement wait_until_job_complete parameter for KubernetesJobOperator (#37998)

1d3010c4ab

2024-03-12

Fix case if 'SparkKubernetesOperator.application_file' is templated file (#38035)

8f773a62c1

2024-03-08

Add GKECreateCustomResourceOperator and GKEDeleteCustomResourceOperator operators (#37616)

a7b7928a2a

2024-03-07

fix: reduce irrelevant error logs for pod events. (#37944)

8e6f78a735

2024-03-06

Use SIGINT signal number instead of signal name (#37905)

ca72f0fd89

2024-03-06

Add GKEListJobsOperator and GKEDescribeJobOperator (#37598)

+
+
+

8.0.1

+

Latest change: 2024-03-04

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

83316b8158

2024-03-04

Prepare docs 1st wave (RC1) March 2024 (#37876)

30f7b2abe6

2024-03-04

Avoid to use too broad 'noqa' (#37862)

d470674912

2024-03-01

Immediately fail the task in case of worker pod having a fatal container state (#37670)

77341ef6a1

2024-02-29

Avoid non-recommended usage of logging (#37792)

cd33c2a6a7

2024-02-27

Migrate executor docs to respective providers (#37728)

c6ba13adf2

2024-02-26

Skip pod cleanup in case of pod creation failed (#37671)

+
+
+

8.0.0

+

Latest change: 2024-02-19

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

fa234e0d22

2024-02-19

Prepare docs 1st wave (RC3) of Providers February 2024 (#37521)

6412b06a7b

2024-02-18

Fix KPO task hanging when pod fails to start within specified timeout (#37514)

d50a25bd35

2024-02-17

Fix KeyError when KPO exits too soon (#37508)

75182363a2

2024-02-17

Prepare docs 1st wave (RC2) of Providers February 2024 (#37471)

5a0be392e6

2024-02-16

Add comment about versions updated by release manager (#37488)

c84efe77a5

2024-02-15

KPO Maintain backward compatibility for execute_complete and trigger run method (#37454)

32ba99b6c2

2024-02-15

Create GKEStartJobOperator and KubernetesJobOperator (#36847)

0be6430938

2024-02-15

Revert "KPO Maintain backward compatibility for execute_complete and trigger run method (#37363)" (#37446)

df132b2dd6

2024-02-15

Add GKEStartKueueInsideClusterOperator (#37072)

0640e6d595

2024-02-14

KPO Maintain backward compatibility for execute_complete and trigger run method (#37363)

34c06c6922

2024-02-14

Convert Kubernetes ApiException status code to string to ensure it's correctly checked (#37405)

bfb054e9e8

2024-02-12

Prepare docs 1st wave of Providers February 2024 (#37326)

053485ba56

2024-02-12

Modify KPO to log container log periodically  (#37279)

f689c3f606

2024-02-12

Add d401 support to kubernetes provider (#37301)

6246eec96f

2024-02-10

Fix occasional attr-undefined for the python_kubernetes_script (#37318)

e99487946a

2024-02-10

The task is stuck in a queued state forever in case of pod launch errors  (#36882)

9a529a8d43

2024-02-10

Fix hanging KPO on deferrable task with do_xcom_push (#37300)

f691adf710

2024-02-09

Fix rendering 'SparkKubernetesOperator.template_body' (#37271)

7932958488

2024-02-05

Fix assignment of template field in '__init__' in 'KubernetesPodOperator' (#37010)

dec2662190

2024-01-30

feat: Switch all class, functions, methods deprecations to decorators (#36876)

c36c4db3f7

2024-01-29

Kubernetes version bump (#37040)

+
+
+

7.14.0

+

Latest change: 2024-01-26

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

cead3da4a6

2024-01-26

Add docs for RC2 wave of providers for 2nd round of Jan 2024 (#37019)

dd627d7f46

2024-01-26

36888-Fix k8 configmap issue in 7.14.0rc1 (#37001)

d78a114aa0

2024-01-23

Increase tenacity wait in read_pod_logs (#36955)

2b4da0101f

2024-01-22

Prepare docs 2nd wave of Providers January 2024 (#36945)

43d192543e

2024-01-20

Template field support for configmaps in the KubernetesPodOperator (#36922)

6dc53524a5

2024-01-20

Create a generic callbacks class for KubernetesPodOperator (#35714)

d3b4a91135

2024-01-20

fix: Avoid retrying after KubernetesPodOperator has been marked as failed (#36749)

6ff96af480

2024-01-18

Fix stacklevel in warnings.warn into the providers (#36831)

142f08abb5

2024-01-12

Change field type for kube_config (#36752)

aa25affec6

2024-01-12

Add SparkKubernetesOperator crd implementation (#22253)

2ffa6e4c4c

2024-01-12

Add support of Pendulum 3 (#36281)

19ebcac239

2024-01-07

Prepare docs 1st wave of Providers January 2024 (#36640)

2f15c95a28

2024-01-03

Changing wording in docstring for CNCF provider (#36547)

6937ae7647

2023-12-30

Speed up autocompletion of Breeze by simplifying provider state (#36499)

+
+
+

7.13.0

+

Latest change: 2023-12-28

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

9b5d6bfe27

2023-12-28

Add documentation for 3rd wave of providers in Deember (#36464)

2bd60771a8

2023-12-26

Remove deprecated input parameters in the k8s pod operator (#36433)

a7700c1567

2023-12-26

Add reminder about update stub file in case of change KubernetesPodOperator's arguments (#36434)

ee219e658d

2023-12-26

Delete get_python_source from Kubernetes decorator after bumping min airflow version to 2.6.0 (#36426)

af9328e6ff

2023-12-26

Remove duplicated methods in K8S pod operator module and import them from helper function (#36427)

3f60482974

2023-12-24

Don't get pod status in KubernetesPodOperator if skip_on_exit_code is not set (#36355)

63544e184d

2023-12-24

Allow changing of 'config_file' in 'KubernetesResourceBaseOperator' (#36397)

+
+
+

7.12.0

+

Latest change: 2023-12-23

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

b15d5578da

2023-12-23

Re-apply updated version numbers to 2nd wave of providers in December (#36380)

f5883d6e7b

2023-12-23

Prepare 2nd wave of providers in December (#36373)

33ee0b98b2

2023-12-22

Add _request_timeout to KPO log fetch calls (#36297)

381922f7c0

2023-12-21

Make pod_name length equal to HOST_NAME_MAX (#36332)

49108e15eb

2023-12-20

Kubernetes executor running slots leak fix (#36240)

5ab43d5541

2023-12-19

Move KubernetesPodTrigger hook to a cached property (#36290)

f81dfd731f

2023-12-17

Add 'pod_template_dict' field to 'KubernetesPodOperator' (#33174)

a398d9d4fa

2023-12-16

KubernetesPodTrigger: add exception stack trace in TriggerEvent (#35716)

cd476acd8f

2023-12-11

Follow BaseHook connection fields method signature in child classes (#36086)

b9c574c61a

2023-12-10

list pods performance optimization (#36092)

+
+
+

7.11.0

+

Latest change: 2023-12-08

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

999b70178a

2023-12-08

Prepare docs 1st wave of Providers December 2023 (#36112)

d0918d77ee

2023-12-07

Bump minimum Airflow version in providers to Airflow 2.6.0 (#36017)

1264316fe7

2023-12-05

Drive-by improvements to convert_env_vars (#36062)

de71a62848

2023-12-05

fix: KPO typing env_vars (#36048)

f5259376b8

2023-11-28

Use fail instead of change_state(failed) in K8S executor (#35900)

623f989329

2023-11-27

Stop converting state to TaskInstanceState when it's None (#35891)

e57232ff8f

2023-11-25

Feature pass dictionary configuration in application_file in SparkKubernetesOperator (#35848)

+
+
+

7.10.0

+

Latest change: 2023-11-24

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

0b23d5601c

2023-11-24

Prepare docs 2nd wave of Providers November 2023 (#35836)

0e157b38a3

2023-11-23

Fix K8S executor override config using pod_override_object (#35185)

ca97feed18

2023-11-23

Revert Remove PodLoggingStatus object #35422 (#35822)

8dc1b23116

2023-11-22

feat: K8S resource operator - CRD (#35600)

99534e47f3

2023-11-19

Use reproducible builds for provider packages (#35693)

99df205f42

2023-11-16

Fix and reapply templates for provider documentation (#35686)

6f51e502df

2023-11-15

Add annotations field into  in KubernetesPodOperator (#35641)

486ccba4cf

2023-11-13

Remove inconsequential code bits in KPO logging (#35416)

31450bbe3c

2023-11-13

Remove non existing params from 'KubernetesResourceBaseOperator' docstring

cd296d2068

2023-11-12

KubernetesExecutor observability Improvements (#35579)

4b1e494f47

2023-11-10

Add bandit to pre-commit to detect common security issues (#34247)

+
+
+

7.9.0

+

Latest change: 2023-11-08

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

1b059c57d6

2023-11-08

Prepare docs 1st wave of Providers November 2023 (#35537)

d6c79ce340

2023-11-07

Remove tenancity on KPO logs inner func consume_logs (#35504)

68b3b7b468

2023-11-07

Simplify KPO multi container log reconciliation logic (#35450)

be2c3b9d9e

2023-11-05

Remove PodLoggingStatus object (#35422)

c67a2b0413

2023-11-05

Use constant for empty xcom result sentinel (#35451)

a61da3cc87

2023-11-04

Add verificationy that provider docs are as expected (#35424)

2023a76037

2023-11-03

Remove before_log in KPO retry and add traceback when interrupted (#35423)

2b0bfea837

2023-11-01

Add startup_check_interval_seconds to PodManager's await_pod_start (#34231)

3724a029da

2023-11-01

Improve clear_not_launched_queued_tasks call duration (#34985)

63cc915cd3

2023-10-31

Switch from Black to Ruff formatter (#35287)

+
+
+

7.8.0

+

Latest change: 2023-10-28

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

d1c58d86de

2023-10-28

Prepare docs 3rd wave of Providers October 2023 - FIX (#35233)

3592ff4046

2023-10-28

Prepare docs 3rd wave of Providers October 2023 (#35187)

85f0ef35b8

2023-10-27

Added to the rendering of KubernetesOperator V1VolumeMount, sub_path (#35129)

d4002261b5

2023-10-26

Replace blocking IO with async IO in AsyncKubernetesHook (#35162)

4767f48a3b

2023-10-25

feat: add hostAliases to pod spec in KubernetesPodOperator (#35063)

4c8c85ccc2

2023-10-23

Consolidate the warning stacklevel in KubernetesPodTrigger (#35079)

dd7ba3cae1

2023-10-19

Pre-upgrade 'ruff==0.0.292' changes in providers (#35053)

b75f9e8806

2023-10-18

Upgrade pre-commits (#35033)

f23170c9dd

2023-10-16

D401 Support - A thru Common (Inclusive) (#34934)

+
+
+

7.7.0

+

Latest change: 2023-10-13

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

e9987d5059

2023-10-13

Prepare docs 1st wave of Providers in October 2023 (#34916)

0c8e30e43b

2023-10-05

Bump min airflow version of providers (#34728)

4234d8db7e

2023-10-04

Fix parsing KubernetesPodOperator multiline logs (#34412)

cbb04e5133

2023-10-01

Remove duplicated logs by reusing PodLogsConsumer (#34127)

bd512007e5

2023-09-28

Fix KubernetesPodTrigger startup timeout (#34579)

7ebf4220c9

2023-09-28

Refactor usage of str() in providers (#34320)

fb92ff8486

2023-09-27

Fix Pod not being removed after istio-sidecar is removed  (#34500)

a169cf2c25

2023-09-26

Update CHANGELOG.rst (#34625)

08729eddbd

2023-09-22

warn level for deprecated set to stacklevel 2 (#34530)

659d94f0ae

2023-09-21

Use 'airflow.exceptions.AirflowException' in providers (#34511)

8ecd576de1

2023-09-14

Refactor shorter defaults in providers (#34347)

+
+
+

7.6.0

+

Latest change: 2023-09-14

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

7574e16e75

2023-09-14

Prepare docs for Sep 2023 2nd wave of Providers (#34360)

de92a81f00

2023-09-13

Move definition of Pod*Exceptions to pod_generator (#34346)

b435b8edef

2023-09-09

Push to xcom before 'KubernetesPodOperator' deferral (#34209)

b5057e0e1f

2023-09-09

Add 'progress_callback' parameter to 'KubernetesPodOperator' (#34153)

c5016f754d

2023-09-08

Refactor: Consolidate import textwrap in providers (#34220)

+
+
+

7.5.1

+

Latest change: 2023-09-08

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

21990ed894

2023-09-08

Prepare docs for 09 2023 - 1st wave of Providers (#34201)

6e1de4f9b9

2023-09-07

fix(providers/spark-kubernetes): respect soft_fail argument when exception is raised (#34167)

1005501365

2023-09-06

Used cached property for hook in SparkKubernetesOperator (#34130)

7731255975

2023-09-06

Refactor: Consolidate import datetime (#34110)

5e6e107f73

2023-09-05

Use 'cached_property' for hook in SparkKubernetesSensor (#34106)

fa5e54c4c5

2023-09-03

Combine similar if logics in providers (#33987)

47bd5dd0e1

2023-09-03

Remove useless string join from providers (#33968)

875387afa5

2023-09-01

Refactor unneeded  jumps in providers (#33833)

ff7dcf4e82

2023-09-01

replace loop by any when looking for a positive value in providers (#33984)

1b122c1503

2023-09-01

Move the try outside the loop when this is possible in kubernetes provider (#33977)

55976af32e

2023-08-31

Replace sequence concatination by unpacking in Airflow providers (#33933)

f66df7f6bc

2023-08-31

Replace dict.items by values when key is not used in providers (#33939)

+
+
+

7.5.0

+

Latest change: 2023-08-29

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

23174ef1bb

2023-08-29

Prepare docs for Aug 2023 3rd wave of Providers (RC2) (#33868)

cede385e93

2023-08-28

Always use 'Literal' from 'typing_extensions' (#33794)

452a978337

2023-08-27

Improve modules import in cncf.kubernetes probvider by move some of them into a type-checking block (#33781)

42bc8fcb6b

2023-08-26

Update pod.py (#33779)

b11525702c

2023-08-26

Use literal dict instead of calling dict() in providers (#33761)

c077d19060

2023-08-26

Prepare docs for Aug 2023 3rd wave of Providers (#33730)

c477031039

2023-08-24

Inspect container state rather than last_state when deciding whether to skip (#33702)

85acbb4ae9

2023-08-24

Refactor: Remove useless str() calls (#33629)

6130993d78

2023-08-24

Fix KubernetesPodOperator duplicating logs when interrupted (#33500)

2dbb963324

2023-08-24

Refactor: Improve detection of duplicates and list sorting (#33675)

75ce4d1923

2023-08-23

Add istio test, use curl /quitquitquit to exit sidecar, and some othe… (#33306)

4bdf908041

2023-08-23

Fix 2.7.0 db migration job errors (#33652)

0ca5f700ab

2023-08-23

Exclude deprecated "operators.kubernetes_pod" module from provider.yaml (#33641)

a54c2424df

2023-08-23

Fix typos (double words and it's/its) (#33623)

7141c42cc3

2023-08-22

Make cluster_context templated (#33604)

4c4981d1ad

2023-08-21

Refactor Sqlalchemy queries to 2.0 style (Part 7) (#32883)

95a930bc0a

2023-08-21

Consolidate import and usage of itertools (#33479)

1cdd82391e

2023-08-21

Simplify conditions on len() in other providers (#33569)

e991f60a79

2023-08-18

Add 'active_deadline_seconds' parameter to 'KubernetesPodOperator' (#33379)

bfe08a79db

2023-08-16

Import utc from datetime and normalize its import (#33450)

46ffc25995

2023-08-14

Adding typing for KPO SCC objects (#33381)

38aada7b8b

2023-08-14

Introducing class constant to make worker pod log lines configurable (#33378)

7e79997594

2023-08-11

D205 Support - Providers - Final Pass (#33303)

+
+
+

7.4.2

+

Latest change: 2023-08-11

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

b5a4d36383

2023-08-11

Prepare docs for Aug 2023 2nd wave of Providers (#33291)

1f6257110d

2023-08-09

Make the 'OnFinishAction' enum inherit from str to support passing it to 'KubernetesPodOperatpor' (#33228)

0b528e2b2e

2023-08-09

Add missing re2 dependency to cncf.kubernetes and celery providers (#33237)

056f1670fe

2023-08-08

Refactor: Simplify code in providers/cncf (#33230)

9556d6d5f6

2023-08-08

Replace State by TaskInstanceState in Airflow executors (#32627)

+
+
+

7.4.1

+

Latest change: 2023-08-05

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

60677b0ba3

2023-08-05

Prepare docs for Aug 2023 1st wave of Providers (#33128)

f4542a30b0

2023-08-04

Fix waiting the base container when reading the logs of other containers (#33127)

4fbbdbc9b1

2023-08-04

Revert "Fix waiting the base container when reading the logs of other containers (#33092)" (#33125)

164526d4c7

2023-08-04

Consider custom pod labels on pod finding process on 'KubernetesPodOperator' (#33057)

d31c77510c

2023-08-04

Fix waiting the base container when reading the logs of other containers (#33092)

900ad8c190

2023-08-04

Fix: Configurable Docker image of 'xcom_sidecar' (#32858)

879fd34e97

2023-08-04

aDd documentation generation for CLI commands from executors (#33081)

f83d63ea54

2023-08-04

Fix 'KubernetesPodOperator' sub classes default container_logs (#33090)

+
+
+

7.4.0

+

Latest change: 2023-07-29

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

d06b7af69a

2023-07-29

Prepare docs for July 2023 3rd wave of Providers (#32875)

bcc7856b80

2023-07-29

Add 'termination_message_policy' parameter to 'KubernetesPodOperator' (#32885)

f31af91dbd

2023-07-29

Raise original import error in CLI vending of executors (#32931)

fcbbf47864

2023-07-29

[AIP-51] Executors vending CLI commands (#29055)

e93460383f

2023-07-26

Move all k8S classes to cncf.kubernetes provider (#32767)

fcc6f284c7

2023-07-22

Update the watcher resource version in SparkK8SOp when it's too old (#32768)

e01323635a

2023-07-13

Add deprecation info to the providers modules and classes docstring (#32536)

+
+
+

7.3.0

+

Latest change: 2023-07-12

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

e7f59a913e

2023-07-12

Prepare docs for July 2023 2nd wave of Providers (#32566)

b3ce116192

2023-07-12

Fix async KPO by waiting pod termination in 'execute_complete' before cleanup (#32467)

c99c03135c

2023-07-08

D205 Support - Providers: Stragglers and new additions (#32447)

9a0f41ba53

2023-07-06

Logging from all containers in KubernetesOperatorPod (#31663)

+
+
+

7.2.0

+

Latest change: 2023-07-06

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

225e3041d2

2023-07-06

Prepare docs for July 2023 wave of Providers (RC2) (#32381)

3878fe6fab

2023-07-05

Remove spurious headers for provider changelogs (#32373)

cb4927a018

2023-07-05

Prepare docs for July 2023 wave of Providers (#32298)

f8593503cb

2023-07-05

Add default_deferrable config (#31712)

df4c8837d0

2023-07-01

Fix KubernetesPodOperator validate xcom json and add retries (#32113)

dd937e51fe

2023-06-30

Add 'on_finish_action' to 'KubernetesPodOperator' (#30718)

8f5de83ee6

2023-06-29

Fix 'KubernetesPodTrigger' waiting strategy (#31348)

8c37b74a20

2023-06-28

D205 Support - Providers: Apache to Common (inclusive) (#32226)

6693bdd72d

2023-06-27

fix spark-kubernetes-operator compatibality (#31798)

09d4718d3a

2023-06-27

Improve provider documentation and README structure (#32125)

+
+
+

7.1.0

+

Latest change: 2023-06-20

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

79bcc2e668

2023-06-20

Prepare RC1 docs for June 2023 wave of Providers (#32001)

8b146152d6

2023-06-20

Add note about dropping Python 3.7 for providers (#32015)

66299338eb

2023-06-18

add a return when the event is yielded in a loop to stop the execution (#31985)

07ea574fed

2023-06-07

Add D400 pydocstyle check (#31742)

d8086a3db5

2023-06-05

Add possibility to disable logging the pod template in a case when task fails (#31595)

def4b53765

2023-06-05

Fix Fargate logging for AWS system tests (#31622)

86b5ba2802

2023-06-04

Remove return statement after yield from triggers class (#31703)

0fa8c44527

2023-06-04

KubernetesResourceOperator - KubernetesDeleteResourceOperator & KubernetesCreateResourceOperator (#29930)

dc5bf3fd02

2023-06-02

Add discoverability for triggers in provider.yaml (#31576)

a59076eaee

2023-06-02

Add D400 pydocstyle check - Providers (#31427)

9fa75aaf7a

2023-05-29

Remove Python 3.7 support (#30963)

+
+
+

7.0.0

+

Latest change: 2023-05-19

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

45548b9451

2023-05-19

Prepare RC2 docs for May 2023 wave of Providers (#31416)

a1f5a5425e

2023-05-19

Remove deprecated features from KubernetesHook (#31402)

54f1fb0574

2023-05-19

Docstring improvements (#31375)

abea189022

2023-05-18

Use '__version__' in providers not 'version' (#31393)

f5aed58d9f

2023-05-18

Fixing circular import error in providers caused by airflow version check (#31379)

d9ff55cf6d

2023-05-16

Prepare docs for May 2023 wave of Providers (#31252)

caeca2d143

2023-05-15

Add protocol to define methods relied upon by KubernetesPodOperator (#31298)

774a5a9038

2023-05-11

Empty xcom result file log message more specific (#31228)

e7cb9ca2c1

2023-05-11

Fix pod describing on system test failure (#31191)

8eab2e54ee

2023-05-10

K8s hook should still work with missing default conn (#31187)

c3c90eaa94

2023-05-10

Add options to KubernetesPodOperator (#30992)

dcf3d39a15

2023-05-08

Fix kubernetes task decorator pickle error (#31110)

0a30706aa7

2023-05-03

Use 'AirflowProviderDeprecationWarning' in providers (#30975)

eef5bc7f16

2023-05-03

Add full automation for min Airflow version for providers (#30994)

a7eb32a5b2

2023-04-30

Bump minimum Airflow version in providers (#30917)

9409446097

2023-04-24

Add cli cmd to list the provider trigger info (#30822)

b5296b7436

2023-04-22

add missing read for K8S config file from conn in deferred 'KubernetesPodOperator'  (#29498)

c585ad51c5

2023-04-22

Upgrade ruff to 0.0.262 (#30809)

+
+
+

6.1.0

+

Latest change: 2023-04-21

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

e46ce78b66

2023-04-21

Prepare docs for adhoc release of providers (#30787)

ebe2f2f626

2023-04-21

Remove skip_exit_code from KubernetesPodOperator (#30788)

afdc95435b

2023-04-21

Add multiple exit code handling in skip logic for 'DockerOperator' and 'KubernetesPodOperator' (#30769)

99a3bf2318

2023-04-19

Deprecate 'skip_exit_code' in 'DockerOperator' and 'KubernetesPodOperator' (#30733)

f511653e5a

2023-04-15

Skip KubernetesPodOperator task when it returns a provided exit code (#29000)

+
+
+

6.0.0

+

Latest change: 2023-04-09

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

874ea9588e

2023-04-09

Prepare docs for ad hoc release of Providers (#30545)

85b9135722

2023-04-08

Use default connection id for KubernetesPodOperator (#28848)

dc4dd9178c

2023-04-05

Allow to set limits for XCOM container (#28125)

d23a3bbed8

2023-04-04

Add mechanism to suspend providers (#30422)

+
+
+

5.3.0

+

Latest change: 2023-04-02

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

55dbf1ff1f

2023-04-02

Prepare docs for April 2023 wave of Providers (#30378)

df49ad179b

2023-03-24

Ensure setup/teardown work on a previously decorated function (#30216)

b8ab594130

2023-03-15

Remove "boilerplate" from all taskflow decorators (#30118)

9a4f674852

2023-03-14

enhance spark_k8s_operator (#29977)

c3867781e0

2023-03-08

adding trigger info to provider yaml (#29950)

1e81a98cc6

2023-03-07

Fix KubernetesPodOperator xcom push when 'get_logs=False' (#29052)

971039454a

2023-03-04

Align cncf provider file names with AIP-21 (#29905)

6d2face107

2023-03-04

Fixed hanged KubernetesPodOperator (#28336)

+
+
+

5.2.2

+

Latest change: 2023-03-03

+ +++++ + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

fcd3c0149f

2023-03-03

Prepare docs for 03/2023 wave of Providers (#29878)

1e536eb43d

2023-02-28

'KubernetesPodOperator._render_nested_template_fields' improved by changing the conditionals for a map (#29760)

dba390e323

2023-02-22

Fix and augment 'check-for-inclusive-language' CI check (#29549)

+
+
+

5.2.1

+

Latest change: 2023-02-18

+ +++++ + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

470fdaea27

2023-02-18

Prepare docs for 02 2023 midmonth wave of Providers (#29589)

9a5c3e0ac0

2023-02-18

Fix @task.kubernetes to receive input and send output (#28942)

+
+
+

5.2.0

+

Latest change: 2023-02-08

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

ce6ae2457e

2023-02-08

Prepare docs for Feb 2023 wave of Providers (#29379)

d26dc22391

2023-02-01

Patch only single label when marking KPO checked (#29279)

246d778e6b

2023-01-30

Add deferrable mode to ''KubernetesPodOperator'' (#29017)

70b84b51a5

2023-01-23

Allow setting the name for the base container within K8s Pod Operator (#28808)

+
+
+

5.1.1

+

Latest change: 2023-01-14

+ +++++ + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

911b708ffd

2023-01-14

Prepare docs for Jan 2023 mid-month wave of Providers (#28929)

ce858a5d71

2023-01-12

Switch to ruff for faster static checks (#28893)

ce677862be

2023-01-07

Fix Incorrect 'await_container_completion' (#28771)

+
+
+

5.1.0

+

Latest change: 2023-01-02

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

5246c009c5

2023-01-02

Prepare docs for Jan 2023 wave of Providers (#28651)

c22fc000b6

2022-12-30

Use labels instead of pod name for pod log read in k8s exec (#28546)

681835a67c

2022-12-21

Add Flink on K8s Operator  (#28512)

38e40c6dc4

2022-12-21

Remove outdated compat imports/code from providers (#28507)

401fc57e8b

2022-12-16

Restructure Docs  (#27235)

bdc3d2e647

2022-12-08

Keep pod name for k8s executor under 63 characters (#28237)

d93240696b

2022-12-05

Allow longer pod names for k8s executor / KPO (#27736)

33c445d92f

2022-12-03

Add volume-related nested template fields for KPO (#27719)

ebd7b67dcb

2022-12-02

Patch "checked" when pod not successful (#27845)

25bdbc8e67

2022-11-26

Updated docs for RC3 wave of providers (#27937)

2e20e9f7eb

2022-11-24

Prepare for follow-up relase for November providers (#27774)

+
+
+

5.0.0

+

Latest change: 2022-11-15

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

12c3c39d1a

2022-11-15

pRepare docs for November 2022 wave of Providers (#27613)

52593b061c

2022-11-11

Enable template rendering for env_vars field for the @task.kubernetes decorator (#27433)

47a2b9ee7f

2022-11-09

Add container_resources as KubernetesPodOperator templatable (#27457)

aefadb8c5b

2022-11-08

Allow xcom sidecar container image to be configurable in KPO (#26766)

2d2f0daad6

2022-11-08

Fix KubernetesHook fail on an attribute absence (#25787)

eee3df4570

2022-11-07

Improve task_id to pod name conversion (#27524)

8c15b0a6d1

2022-11-07

Use log.exception where more economical than log.error (#27517)

20ecefa416

2022-11-05

KPO should use hook's get namespace method to get namespace (#27516)

701239abc3

2022-11-05

Remove deprecated backcompat objects for KPO (#27518)

9337aa92c0

2022-11-05

Remove support for node_selectors param in KPO (#27515)

3aadc44a13

2022-11-03

Remove unused backcompat method in k8s hook (#27490)

0c26ec07be

2022-10-28

Drop support for providing ''resource'' as dict in ''KubernetesPodOperator'' (#27197)

4797a0322e

2022-10-28

Fix log message for kubernetes hooks (#26999)

9ab1a6a3e7

2022-10-27

Update old style typing (#26872)

734995ff26

2022-10-26

Add deprecation warning re unset namespace in k8s hook (#27202)

78b8ea2f22

2022-10-24

Move min airflow version to 2.3.0 for all providers (#27196)

2a34dc9e84

2022-10-23

Enable string normalization in python formatting - providers (#27205)

14a45872e2

2022-10-22

Remove extra__kubernetes__ prefix from k8s hook extras (#27021)

3ecb8dd025

2022-10-22

Make namespace optional for KPO (#27116)

c9e57687b0

2022-10-21

Make pod name optional in KubernetesPodOperator (#27120)

2752f2add1

2022-10-12

Deprecate use of core get_kube_client in PodManager (#26848)

5c97e5be48

2022-10-10

add container_name option for SparkKubernetesSensor (#26560)

53d68049d9

2022-10-04

Don't consider airflow core conf for KPO (#26849)

f8db64c35c

2022-09-28

Update docs for September Provider's release (#26731)

+
+
+

4.4.0

+

Latest change: 2022-09-22

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

1a07cbe423

2022-09-22

Prepare to release cncf.kubernetes provider (#26588)

e60a459d56

2022-09-14

Avoid calculating all elements when one item is needed (#26377)

06acf40a43

2022-09-13

Apply PEP-563 (Postponed Evaluation of Annotations) to non-core airflow (#26289)

4b26c8c541

2022-09-09

feat(KubernetesPodOperator): Add support of container_security_context (#25530)

0eb0b543a9

2022-08-23

Add @task.kubernetes taskflow decorator (#25663)

db5543ef60

2022-08-22

pretty print KubernetesPodOperator rendered template env_vars (#25850)

ccdd73ec50

2022-08-22

Wait for xcom sidecar container to start before sidecar exec (#25055)

+
+
+

4.3.0

+

Latest change: 2022-08-10

+ +++++ + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

e5ac6c7cfb

2022-08-10

Prepare docs for new providers release (August 2022) (#25618)

c8af0592c0

2022-07-26

Improve taskflow type hints with ParamSpec (#25173)

f05a06537b

2022-07-16

Fix xcom_sidecar stuck problem (#24993)

+
+
+

4.2.0

+

Latest change: 2022-07-13

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

d2459a241b

2022-07-13

Add documentation for July 2022 Provider's release (#25030)

ef79a0d1c4

2022-07-11

Only assert stuff for mypy when type checking (#24937)

e2fd41f7b1

2022-07-04

Remove 'xcom_push' flag from providers (#24823)

9d307102b4

2022-06-29

More typing and minor refactor for kubernetes (#24719)

0de31bd73a

2022-06-29

Move provider dependencies to inside provider folders (#24672)

45b11d4ed1

2022-06-29

Use our yaml util in all providers (#24720)

510a6bab45

2022-06-28

Remove 'hook-class-names' from provider.yaml (#24702)

5326da4b83

2022-06-28

Add 'airflow_kpo_in_cluster' label to KPO pods (#24658)

45f4290712

2022-06-28

Rename 'resources' arg in Kub op to k8s_resources (#24673)

9c59831ee7

2022-06-21

Update providers to use functools compat for ''cached_property'' (#24582)

78ac48872b

2022-06-21

Use found pod for deletion in KubernetesPodOperator (#22092)

dba3e4ec51

2022-06-15

Revert "Fix await_container_completion condition (#23883)" (#24474)

+
+
+

4.1.0

+

Latest change: 2022-06-09

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

dcdcf3a2b8

2022-06-09

Update release notes for RC2 release of Providers for May 2022 (#24307)

717a7588bc

2022-06-07

Update package description to remove double min-airflow specification (#24292)

b1ad017cee

2022-06-07

pydocstyle D202 added (#24221)

aeabe994b3

2022-06-07

Prepare docs for May 2022 provider's release (#24231)

98b4e48fbc

2022-06-06

Add param docs to KubernetesHook and KubernetesPodOperator (#23955) (#24054)

42abbf0d61

2022-06-06

Fix await_container_completion condition (#23883)

027b707d21

2022-06-05

Add explanatory note for contributors about updating Changelog (#24229)

7ad4e67c1a

2022-06-03

Migrate Cncf.Kubernetes example DAGs to new design #22441 (#24132)

60eb9e106f

2022-05-31

Use KubernetesHook to create api client in KubernetesPodOperator (#20578)

e240132934

2022-05-27

[FEATURE] KPO use K8S hook (#22086)

6bbe015905

2022-05-26

Use "remote" pod when patching KPO pod as "checked" (#23676)

ec6761a5c0

2022-05-23

Clean up f-strings in logging calls (#23597)

064c41afda

2022-05-20

Don't use the root logger in KPO _suppress function (#23835)

+
+
+

4.0.2

+

Latest change: 2022-05-12

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

75c60923e0

2022-05-12

Prepare provider documentation 2022.05.11 (#23631)

2eeb120bf4

2022-05-12

Revert "Fix k8s pod.execute randomly stuck indefinitely by logs consumption (#23497) (#23618)" (#23656)

ee342b85b9

2022-05-11

Fix k8s pod.execute randomly stuck indefinitely by logs consumption (#23497) (#23618)

863b257642

2022-05-10

Fix: Exception when parsing log #20966 (#23301)

faae9faae3

2022-05-10

Fixed Kubernetes Operator large xcom content Defect  (#23490)

dbdcd0fd1d

2022-04-30

Clarify 'reattach_on_restart' behavior (#23377)

a914ec22c1

2022-04-30

Add YANKED to yanked releases of the cncf.kubernetes (#23378)

+
+
+

4.0.1

+

Latest change: 2022-04-30

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

11bbe471cd

2022-04-30

Prepare documentation for cncf.kubernetes 4.0.1 release (#23374)

8e3abe4180

2022-04-29

Fix ''KubernetesPodOperator'' with 'KubernetesExecutor'' on 2.3.0 (#23371)

8b6b0848a3

2022-04-23

Use new Breese for building, pulling and verifying the images. (#23104)

c7399c7190

2022-04-21

KubernetesHook should try incluster first when not otherwise configured (#23126)

70eede5dd6

2022-04-20

Fix KPO to have hyphen instead of period (#22982)

c3d883a971

2022-04-19

KubernetesPodOperator should patch "already checked" always (#22734)

d81703c577

2022-04-14

Add k8s container's error message in airflow exception (#22871)

3c5bc73579

2022-04-12

Delete old Spark Application in SparkKubernetesOperator (#21092)

6933022e94

2022-04-10

Fix new MyPy errors in main (#22884)

04082ac091

2022-04-09

Cleanup dup code now that k8s provider requires 2.3.0+ (#22845)

+
+
+

4.0.0

+

Latest change: 2022-04-07

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

56ab82ed7a

2022-04-07

Prepare mid-April provider documentation. (#22819)

67e2723b73

2022-03-29

Log traceback only on ''DEBUG'' for KPO logs read interruption (#22595)

6db30f3207

2022-03-29

Update our approach for executor-bound dependencies (#22573)

0d64d66cea

2022-03-28

Stop crashing when empty logs are received from kubernetes client (#22566)

0a99be7411

2022-03-22

Optionally not follow logs in KPO pod_manager (#22412)

+
+
+

3.1.2

+

Latest change: 2022-03-22

+ +++++ + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

d7dbfb7e26

2022-03-22

Add documentation for bugfix release of Providers (#22383)

0f977daa3c

2022-03-22

Fix "run_id" k8s and elasticsearch compatibility with Airflow 2.1 (#22385)

7bd165fbe2

2022-03-16

Remove RefreshConfiguration workaround for K8s token refreshing (#20759)

+
+
+

3.1.1

+

Latest change: 2022-03-14

+ +++++ + + + + + + + + + + + + +

Commit

Committed

Subject

16adc035b1

2022-03-14

Add documentation for Classifier release for March 2022 (#22226)

+
+
+

3.1.0

+

Latest change: 2022-03-07

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

f5b96315fe

2022-03-07

Add documentation for Feb Providers release (#22056)

8d8d072289

2022-03-03

Change KubePodOperator labels from exeuction_date to run_id (#21960)

6c37e47cf6

2022-03-02

Add map_index label to mapped KubernetesPodOperator (#21916)

351fa53432

2022-03-01

Fix Kubernetes example with wrong operator casing (#21898)

a159ae828f

2022-02-25

Remove types from KPO docstring (#21826)

0a3ff43d41

2022-02-08

Add pre-commit check for docstring param types (#21398)

+
+
+

3.0.2

+

Latest change: 2022-02-08

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

d94fa37830

2022-02-08

Fixed changelog for January 2022 (delayed) provider's release (#21439)

6c3a67d4fc

2022-02-05

Add documentation for January 2021 providers release (#21257)

4a73d8f3d1

2022-02-01

Add missed deprecations for cncf (#20031)

cb73053211

2022-01-27

Add optional features in providers. (#21074)

602abe8394

2022-01-20

Remove ':type' lines now sphinx-autoapi supports typehints (#20951)

428bd5f228

2022-01-10

Make ''delete_pod'' change more prominent in K8s changelog (#20753)

5569b868a9

2022-01-09

Fix MyPy Errors for providers: Tableau, CNCF, Apache (#20654)

+
+
+

3.0.1

+

Latest change: 2022-01-08

+ +++++ + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

da9210e89c

2022-01-08

Add documentation for an ad-hoc release of 2 providers (#20765)

7222f68d37

2022-01-04

Update Kubernetes library version (#18797)

+
+
+

3.0.0

+

Latest change: 2021-12-31

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

f77417eb0d

2021-12-31

Fix K8S changelog to be PyPI-compatible (#20614)

97496ba2b4

2021-12-31

Update documentation for provider December 2021 release (#20523)

83f8e178ba

2021-12-31

Even more typing in operators (template_fields/ext) (#20608)

746ee587da

2021-12-31

Delete pods by default in KubernetesPodOperator (#20575)

d56ff765e1

2021-12-30

Implement dry_run for KubernetesPodOperator (#20573)

e63417553f

2021-12-30

Move pod_mutation_hook call from PodManager to KubernetesPodOperator (#20596)

ca6c210b7d

2021-12-30

Rename ''PodLauncher'' to ''PodManager'' (#20576)

e07e831946

2021-12-30

Clarify docstring for ''build_pod_request_obj'' in K8s providers (#20574)

d56e7b56bb

2021-12-30

Fix template_fields type to have MyPy friendly Sequence type (#20571)

a0821235fb

2021-12-30

Use typed Context EVERYWHERE (#20565)

f200bb1977

2021-12-29

Simplify ''KubernetesPodOperator'' (#19572)

4b8a1201ae

2021-12-16

Fix Volume/VolumeMount KPO DeprecationWarning (#19726)

2fb5e1d0ec

2021-12-15

Fix cached_property MyPy declaration and related MyPy errors (#20226)

f9eab1c185

2021-12-06

Add params config, in_cluster, and cluster_context to KubernetesHook (#19695)

+
+
+

2.2.0

+

Latest change: 2021-11-30

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

853576d901

2021-11-30

Update documentation for November 2021 provider's release (#19882)

fe682ec3d3

2021-11-24

Fix duplicate changelog entries (#19759)

0d60d1af41

2021-11-23

Checking event.status.container_statuses before filtering (#19713)

1e57022953

2021-11-19

Added namespace as a template field in the KPO. (#19718)

f7410dfba2

2021-11-19

Coalesce 'extra' params to None in KubernetesHook (#19694)

bf5f452413

2021-11-08

Change to correct type in KubernetesPodOperator (#19459)

854b70b904

2021-11-07

Decouple name randomization from name kwarg (#19398)

+
+
+

2.1.0

+

Latest change: 2021-10-29

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

d9567eb106

2021-10-29

Prepare documentation for October Provider's release (#19321)

0a6850647e

2021-10-21

Update docstring to let users use 'node_selector' (#19057)

1571f80546

2021-10-14

Add pre-commit hook for common misspelling check in files (#18964)

b2045d6d1d

2021-10-13

Add more type hints to PodLauncher (#18928)

c8b86e69e4

2021-10-12

Add more information to PodLauncher timeout error (#17953)

+
+
+

2.0.3

+

Latest change: 2021-09-30

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

840ea3efb9

2021-09-30

Update documentation for September providers release (#18613)

ef037e7021

2021-09-29

Static start_date and default arg cleanup for misc. provider example DAGs (#18597)

7808be7ffb

2021-09-21

Make Kubernetes job description fit on one log line (#18377)

b8d06e812a

2021-09-08

Fix KubernetesPodOperator reattach when not deleting pods (#18070)

64d2f5488f

2021-09-07

Do not fail KubernetesPodOperator tasks if log reading fails (#17649)

0a68588479

2021-08-30

Add August 2021 Provider's documentation (#17890)

42e13e1a5a

2021-08-30

Remove all deprecation warnings in providers (#17900)

+
+
+

2.0.2

+

Latest change: 2021-08-24

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

bb5602c652

2021-08-24

Prepare release for Kubernetes Provider (#17798)

be75dcd39c

2021-08-23

Update description about the new ''connection-types'' provider meta-data

73d2b720e0

2021-08-21

Fix using XCom with ''KubernetesPodOperator'' (#17760)

76ed2a49c6

2021-08-19

Import Hooks lazily individually in providers manager (#17682)

97428efc41

2021-08-02

Fix messed-up changelog in 3 providers (#17380)

b0b2591071

2021-07-27

Fix static checks (#17256)

997f7d0beb

2021-07-27

Update spark_kubernetes.py (#17237)

+
+
+

2.0.1

+

Latest change: 2021-07-26

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

87f408b1e7

2021-07-26

Prepares docs for Rc2 release of July providers (#17116)

d48b4e0caf

2021-07-21

Simplify 'default_args' in Kubernetes example DAGs (#16870)

3939e84161

2021-07-20

Enable using custom pod launcher in Kubernetes Pod Operator (#16945)

d02ded65ea

2021-07-15

Fixed wrongly escaped characters in amazon's changelog (#17020)

b916b75079

2021-07-15

Prepare documentation for July release of providers. (#17015)

b2c66e45b7

2021-07-11

BugFix: Using 'json' string in template_field causes issue with K8s Operators (#16930)

9d6ae609b6

2021-06-28

Updating task dependencies (#16624)

866a601b76

2021-06-28

Removes pylint from our toolchain (#16682)

+
+
+

2.0.0

+

Latest change: 2021-06-18

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

bbc627a3da

2021-06-18

Prepares documentation for rc2 release of Providers (#16501)

4c9735ff9b

2021-06-17

Fix unsuccessful KubernetesPod final_state call when 'is_delete_operator_pod=True' (#15490)

cbf8001d76

2021-06-16

Synchronizes updated changelog after buggfix release (#16464)

1fba5402bb

2021-06-15

More documentation update for June providers release (#16405)

4752fb3eb8

2021-06-14

Fix issue with parsing error logs in the KPO (#15638)

9c94b72d44

2021-06-07

Updated documentation for June 2021 provider release (#16294)

2f16757e1a

2021-06-03

Bug Pod Template File Values Ignored (#16095)

476d0f6e3d

2021-05-22

Bump pyupgrade v2.13.0 to v2.18.1 (#15991)

85b2ccb0c5

2021-05-20

Add 'KubernetesPodOperat' 'pod-template-file' jinja template support (#15942)

733bec9a04

2021-05-20

Bug Fix Pod-Template Affinity Ignored due to empty Affinity K8S Object (#15787)

37d549bde7

2021-05-14

Save pod name to xcom for KubernetesPodOperator (#15755)

37681bca00

2021-05-07

Auto-apply apply_default decorator (#15667)

+
+
+

1.2.0

+

Latest change: 2021-05-01

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

807ad32ce5

2021-05-01

Prepares provider release after PIP 21 compatibility (#15576)

5b2fe0e740

2021-04-27

Add Connection Documentation for Popular Providers (#15393)

53fc1a9679

2021-04-26

Change KPO node_selectors warning to proper deprecationwarning (#15507)

d3cc67aa7a

2021-04-24

Fix timeout when using XCom with KubernetesPodOperator (#15388)

be421a6b07

2021-04-23

Fix labels on the pod created by ''KubernetsPodOperator'' (#15492)

44480d3673

2021-04-14

Require 'name' with KubernetesPodOperator (#15373)

b4770725a3

2021-04-12

Add links to new modules for deprecated modules (#15316)

+
+
+

1.1.0

+

Latest change: 2021-04-07

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

1806670383

2021-04-07

Retry pod launching on 409 ApiExceptions (#15137)

042be2e4e0

2021-04-06

Updated documentation for provider packages before April release (#15236)

6d7a70b88e

2021-04-05

Separate Kubernetes pod_launcher from core airflow (#15165)

00453dc4a2

2021-03-20

Add ability to specify api group and version for Spark operators (#14898)

68e4c4dcb0

2021-03-20

Remove Backport Providers (#14886)

e7bb17aeb8

2021-03-06

Use built-in 'cached_property' on Python 3.8 where possible (#14606)

7daebefd15

2021-03-05

Use libyaml C library when available. (#14577)

+
+
+

1.0.2

+

Latest change: 2021-02-27

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

589d6dec92

2021-02-27

Prepare to release the next wave of providers: (#14487)

809b4f9b18

2021-02-23

Unique pod name (#14186)

649335c043

2021-02-07

Template k8s.V1EnvVar without adding custom attributes to dict. (#14123)

d4c4db8a18

2021-02-05

Allow users of the KPO to template environment variables (#14083)

10343ec29f

2021-02-05

Corrections in docs and tools after releasing provider RCs (#14082)

+
+
+

1.0.1

+

Latest change: 2021-02-04

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

88bdcfa0df

2021-02-04

Prepare to release a new wave of providers. (#14013)

ac2f72c98d

2021-02-01

Implement provider versioning tools (#13767)

a9ac2b040b

2021-01-23

Switch to f-strings using flynt. (#13732)

1b9e3d1c28

2021-01-22

Revert "Fix error with quick-failing tasks in KubernetesPodOperator (#13621)" (#13835)

94d3ed61d6

2021-01-21

Fix error with quick-failing tasks in KubernetesPodOperator (#13621)

3fd5ef3555

2021-01-21

Add missing logos for integrations (#13717)

295d66f914

2020-12-30

Fix Grammar in PIP warning (#13380)

7a560ab6de

2020-12-24

Pass image_pull_policy in KubernetesPodOperator correctly (#13289)

6cf76d7ac0

2020-12-18

Fix typo in pip upgrade command :( (#13148)

+
+
+

1.0.0

+

Latest change: 2020-12-09

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

32971a1a2d

2020-12-09

Updates providers versions to 1.0.0 (#12955)

b40dffa085

2020-12-08

Rename remaing modules to match AIP-21 (#12917)

9b39f24780

2020-12-08

Add support for dynamic connection form fields per provider (#12558)

bd90136aaf

2020-11-30

Move operator guides to provider documentation packages (#12681)

2037303eef

2020-11-29

Adds support for Connection/Hook discovery from providers (#12466)

de3b1e687b

2020-11-28

Move connection guides to provider documentation packages (#12653)

c02a3f59e4

2020-11-23

Spark-on-k8s sensor logs - properly pass defined namespace to pod log call (#11199)

c34ef853c8

2020-11-20

Separate out documentation building per provider  (#12444)

9e089ab895

2020-11-19

Fix Kube tests (#12479)

d32fe78c0d

2020-11-18

Update readmes for cncf.kube provider fixes (#12457)

d84a52dc8f

2020-11-18

Fix broken example_kubernetes DAG (#12455)

7c8b71d201

2020-11-18

Fix backwards compatibility further (#12451)

0080354502

2020-11-18

Update provider READMEs for 1.0.0b2 batch release (#12449)

7ca0b6f121

2020-11-18

Enable Markdownlint rule MD003/heading-style/header-style (#12427) (#12438)

763b40d223

2020-11-18

Raise correct Warning in kubernetes/backcompat/volume_mount.py (#12432)

bc4bb30588

2020-11-18

Fix docstrings for Kubernetes Backcompat module (#12422)

cab86d80d4

2020-11-17

Make K8sPodOperator backwards compatible (#12384)

ae7cb4a1e2

2020-11-17

Update wrong commit hash in backport provider changes (#12390)

6889a333cf

2020-11-15

Improvements for operators and hooks ref docs (#12366)

221f809c1b

2020-11-14

Fix full_pod_spec for k8spodoperator (#12354)

7825e8f590

2020-11-13

Docs installation improvements (#12304)

85a18e13d9

2020-11-09

Point at pypi project pages for cross-dependency of provider packages (#12212)

59eb5de78c

2020-11-09

Update provider READMEs for up-coming 1.0.0beta1 releases (#12206)

3f59e75cdf

2020-11-09

KubernetesPodOperator: use randomized name to get the failure status (#12171)

b2a28d1590

2020-11-09

Moves provider packages scripts to dev (#12082)

7825be50d8

2020-11-05

Randomize pod name (#12117)

91a64db505

2020-11-04

Format all files (without excepions) by black (#12091)

4e8f9cc8d0

2020-11-03

Enable Black - Python Auto Formmatter (#9550)

8c42cf1b00

2020-11-03

Use PyUpgrade to use Python 3.6 features (#11447)

5a439e84eb

2020-10-26

Prepare providers release 0.0.2a1 (#11855)

872b1566a1

2020-10-25

Generated backport providers readmes/setup for 2020.10.29 (#11826)

53e6062105

2020-10-21

Enforce strict rules for yamllint (#11709)

349b0811c3

2020-10-20

Add D200 pydocstyle check (#11688)

eee4e30f2c

2020-10-15

Add better debug logging to K8sexec and K8sPodOp (#11502)

16e7129719

2020-10-13

Added support for provider packages for Airflow 2.0 (#11487)

8640fb6c10

2020-10-09

fix tests (#11368)

298052fcee

2020-10-10

[airflow/providers/cncf/kubernetes] correct hook methods name (#11008)

49aad025b5

2020-10-09

Users can specify sub-secrets and paths k8spodop (#11369)

b93b6c5be3

2020-10-05

Allow labels in KubernetesPodOperator to be templated (#10796)

0a0e1af800

2020-10-03

Fix Broken Markdown links in Providers README TOC (#11249)

ca4238eb4d

2020-10-02

Fixed month in backport packages to October (#11242)

5220e4c384

2020-10-02

Prepare Backport release 2020.09.07 (#11238)

a888198c27

2020-09-27

Allow overrides for pod_template_file (#11162)

0161b5ea2b

2020-09-26

Increasing type coverage for multiple provider (#11159)

e3f96ce7a8

2020-09-24

Fix incorrect Usage of Optional[bool] (#11138)

f3e87c5030

2020-09-22

Add D202 pydocstyle check (#11032)

b61225a885

2020-09-21

Add D204 pydocstyle check (#11031)

cba51d49ee

2020-09-17

Simplify the K8sExecutor and K8sPodOperator (#10393)

1294e15d44

2020-09-16

KubernetesPodOperator template fix (#10963)

5d6d5a2f7d

2020-09-14

Allow to specify path to kubeconfig in KubernetesHook (#10453)

7edfac957b

2020-09-09

Add connection caching to KubernetesHook (#10447)

9549274d11

2020-09-09

Upgrade black to 20.8b1 (#10818)

90c1505686

2020-09-04

Make grace_period_seconds option on K8sPodOperator (#10727)

338b412c04

2020-09-02

Add on_kill support for the KubernetesPodOperator (#10666)

596bc13379

2020-08-31

Adds 'cncf.kubernetes' package back to backport provider packages. (#10659)

1e5aa4465c

2020-08-26

Spark-on-K8S sensor - add driver logs (#10023)

fdd9b6f65b

2020-08-25

Enable Black on Providers Packages (#10543)

2f2d8dbfaf

2020-08-25

Remove all "noinspection" comments native to IntelliJ (#10525)

7c206a82a6

2020-08-22

Replace assigment with Augmented assignment (#10468)

8cd2be9e16

2020-08-11

Fix KubernetesPodOperator reattachment (#10230)

cdec301254

2020-08-07

Add correct signature to all operators and sensors (#10205)

24c8e4c2d6

2020-08-06

Changes to all the constructors to remove the args argument (#10163)

aeea71274d

2020-08-02

Remove 'args' parameter from provider operator constructors (#10097)

f1fd3e2c45

2020-07-31

Fix typo on reattach property of kubernetespodoperator (#10056)

03c4351744

2020-07-31

Allow 'image' in 'KubernetesPodOperator' to be templated (#10068)

88c1603060

2020-07-31

Improve docstring note about GKEStartPodOperator on KubernetesPodOperator (#10049)

7d24b088cd

2020-07-25

Stop using start_date in default_args in example_dags (2) (#9985)

33f0cd2657

2020-07-22

apply_default keeps the function signature for mypy (#9784)

c2db0dfeb1

2020-07-22

More strict rules in mypy (#9705) (#9906)

719ae2bf62

2020-07-22

Dump Pod as YAML in logs for KubernetesPodOperator (#9895)

840799d559

2020-07-20

Improve KubernetesPodOperator guide (#9079)

44d4ae809c

2020-07-06

Upgrade to latest pre-commit checks (#9686)

8bd15ef634

2020-07-01

Switches to Helm Chart for Kubernetes tests (#9468)

40bf8f28f9

2020-06-18

Detect automatically the lack of reference to the guide in the operator descriptions (#9290)

1d36b0303b

2020-05-23

Fix references in docs (#8984)

e742ef7c70

2020-05-23

Fix typo in test_project_structure (#8978)

375d1ca229

2020-05-19

Release candidate 2 for backport packages 2020.05.20 (#8898)

12c5e5d8ae

2020-05-17

Prepare release candidate for backport packages (#8891)

8985df0bfc

2020-05-16

Monitor pods by labels instead of names (#6377)

f3521fb0e3

2020-05-16

Regenerate readme files for backport package release (#8886)

92585ca4cb

2020-05-15

Added automated release notes generation for backport operators (#8807)

f82ad452b0

2020-05-15

Fix KubernetesPodOperator pod name length validation (#8829)

1ccafc617c

2020-04-02

Add spark_kubernetes system test (#7875)

cd546b664f

2020-03-23

Add missing call to Super class in 'cncf' & 'docker' providers (#7825)

6c39a3bf97

2020-03-10

[AIRFLOW-6542] Add spark-on-k8s operator/hook/sensor (#7163)

42eef38217

2020-03-07

[AIRFLOW-6877] Add cross-provider dependencies as extras (#7506)

3320e432a1

2020-02-24

[AIRFLOW-6817] Lazy-load 'airflow.DAG' to keep user-facing API untouched (#7517)

0ec2774120

2020-02-24

[AIRFLOW-5629] Implement Kubernetes priorityClassName in KubernetesPodOperator (#7395)

9cbd7de6d1

2020-02-18

[AIRFLOW-6792] Remove _operator/_hook/_sensor in providers package and add tests (#7412)

967930c0cb

2020-02-11

[AIRFLOW-5413] Allow K8S worker pod to be configured from JSON/YAML file (#6230)

96f834389e

2020-02-03

[AIRFLOW-6678] Pull event logs from Kubernetes (#7292)

97a429f9d0

2020-02-02

[AIRFLOW-6714] Remove magic comments about UTF-8 (#7338)

cf141506a2

2020-02-02

[AIRFLOW-6708] Set unique logger names (#7330)

373c6aa4a2

2020-01-30

[AIRFLOW-6682] Move GCP classes to providers package (#7295)

83c037873f

2020-01-30

[AIRFLOW-6674] Move example_dags in accordance with AIP-21 (#7287)

059eda05f8

2020-01-21

[AIRFLOW-6610] Move software classes to providers package (#7231)

+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/configurations-ref.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/configurations-ref.html new file mode 100644 index 00000000000..b912bdbfda4 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/configurations-ref.html @@ -0,0 +1,1409 @@ + + + + + + + + + + + + Configuration Reference — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+
+
+

Configuration Reference

+

This page contains the list of all available Airflow configurations for the +apache-airflow-providers-cncf-kubernetes provider that can be set in the airflow.cfg file or using environment variables.

+
+

Note

+

The configuration embedded in provider packages started to be used as of Airflow 2.7.0. Previously the +configuration was described and configured in the Airflow core package - so if you are using Airflow +below 2.7.0, look at Airflow documentation for the list of available configuration options +that were available in Airflow core.

+
+
+

Note

+

For more information see Setting Configuration Options.

+
+
+
+ +
+

[kubernetes_executor]

+
+

api_client_retry_configuration

+

Kwargs to override the default urllib3 Retry used in the kubernetes API client

+
+
Type
+

string

+
+
Default
+

''

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__API_CLIENT_RETRY_CONFIGURATION

+
+
Example
+

{ "total": 3, "backoff_factor": 0.5 }

+
+
+
+
+

cluster_context

+

When running with in_cluster=False change the default cluster_context or config_file +options to Kubernetes client. Leave blank these to use default behaviour like kubectl has.

+
+
Type
+

string

+
+
Default
+

None

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__CLUSTER_CONTEXT

+
+
+
+
+

config_file

+

Path to the kubernetes configfile to be used when in_cluster is set to False

+
+
Type
+

string

+
+
Default
+

None

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__CONFIG_FILE

+
+
+
+
+

delete_option_kwargs

+

Optional keyword arguments to pass to the delete_namespaced_pod kubernetes client +core_v1_api method when using the Kubernetes Executor. +This should be an object and can contain any of the options listed in the v1DeleteOptions +class defined here: +https://github.com/kubernetes-client/python/blob/41f11a09995efcd0142e25946adc7591431bfb2f/kubernetes/client/models/v1_delete_options.py#L19

+
+
Type
+

string

+
+
Default
+

''

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__DELETE_OPTION_KWARGS

+
+
Example
+

{"grace_period_seconds": 10}

+
+
+
+
+

delete_worker_pods

+

If True, all worker pods will be deleted upon termination

+
+
Type
+

string

+
+
Default
+

True

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__DELETE_WORKER_PODS

+
+
+
+
+

delete_worker_pods_on_failure

+

If False (and delete_worker_pods is True), +failed worker pods will not be deleted so users can investigate them. +This only prevents removal of worker pods where the worker itself failed, +not when the task it ran failed.

+
+
Type
+

string

+
+
Default
+

False

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__DELETE_WORKER_PODS_ON_FAILURE

+
+
+
+
+

enable_tcp_keepalive

+

Enables TCP keepalive mechanism. This prevents Kubernetes API requests to hang indefinitely +when idle connection is time-outed on services like cloud load balancers or firewalls.

+
+
Type
+

boolean

+
+
Default
+

True

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__ENABLE_TCP_KEEPALIVE

+
+
+
+
+

in_cluster

+

Use the service account kubernetes gives to pods to connect to kubernetes cluster. +It’s intended for clients that expect to be running inside a pod running on kubernetes. +It will raise an exception if called from a process not running in a kubernetes environment.

+
+
Type
+

string

+
+
Default
+

True

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__IN_CLUSTER

+
+
+
+
+

kube_client_request_args

+

Keyword parameters to pass while calling a kubernetes client core_v1_api methods +from Kubernetes Executor provided as a single line formatted JSON dictionary string. +List of supported params are similar for all core_v1_apis, hence a single config +variable for all apis. See: +https://raw.githubusercontent.com/kubernetes-client/python/41f11a09995efcd0142e25946adc7591431bfb2f/kubernetes/client/api/core_v1_api.py

+
+
Type
+

string

+
+
Default
+

''

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__KUBE_CLIENT_REQUEST_ARGS

+
+
+
+
+

logs_task_metadata

+

Flag to control the information added to kubernetes executor logs for better traceability

+
+
Type
+

boolean

+
+
Default
+

False

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__LOGS_TASK_METADATA

+
+
+
+
+

multi_namespace_mode

+

Allows users to launch pods in multiple namespaces. +Will require creating a cluster-role for the scheduler, +or use multi_namespace_mode_namespace_list configuration.

+
+
Type
+

boolean

+
+
Default
+

False

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__MULTI_NAMESPACE_MODE

+
+
+
+
+

multi_namespace_mode_namespace_list

+

If multi_namespace_mode is True while scheduler does not have a cluster-role, +give the list of namespaces where the scheduler will schedule jobs +Scheduler needs to have the necessary permissions in these namespaces.

+
+
Type
+

string

+
+
Default
+

''

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__MULTI_NAMESPACE_MODE_NAMESPACE_LIST

+
+
+
+
+

namespace

+

The Kubernetes namespace where airflow workers should be created. Defaults to default

+
+
Type
+

string

+
+
Default
+

default

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__NAMESPACE

+
+
+
+
+

pod_template_file

+

Path to the YAML pod file that forms the basis for KubernetesExecutor workers.

+
+

See also

+

pod_template_file

+
+
+
Type
+

string

+
+
Default
+

''

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__POD_TEMPLATE_FILE

+
+
+
+
+

ssl_ca_cert

+

Path to a CA certificate to be used by the Kubernetes client to verify the server’s SSL certificate.

+
+
Type
+

string

+
+
Default
+

''

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__SSL_CA_CERT

+
+
+
+
+

task_publish_max_retries

+

The Maximum number of retries for queuing the task to the kubernetes scheduler when +failing due to Kube API exceeded quota errors before giving up and marking task as failed. +-1 for unlimited times.

+
+
Type
+

integer

+
+
Default
+

0

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__TASK_PUBLISH_MAX_RETRIES

+
+
+
+
+

tcp_keep_cnt

+

When the enable_tcp_keepalive option is enabled, if Kubernetes API does not respond +to a keepalive probe, TCP retransmits the probe tcp_keep_cnt number of times before +a connection is considered to be broken.

+
+
Type
+

integer

+
+
Default
+

6

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__TCP_KEEP_CNT

+
+
+
+
+

tcp_keep_idle

+

When the enable_tcp_keepalive option is enabled, TCP probes a connection that has +been idle for tcp_keep_idle seconds.

+
+
Type
+

integer

+
+
Default
+

120

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__TCP_KEEP_IDLE

+
+
+
+
+

tcp_keep_intvl

+

When the enable_tcp_keepalive option is enabled, if Kubernetes API does not respond +to a keepalive probe, TCP retransmits the probe after tcp_keep_intvl seconds.

+
+
Type
+

integer

+
+
Default
+

30

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__TCP_KEEP_INTVL

+
+
+
+
+

verify_ssl

+

Set this to false to skip verifying SSL certificate of Kubernetes python client.

+
+
Type
+

boolean

+
+
Default
+

True

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__VERIFY_SSL

+
+
+
+
+

worker_container_repository

+

The repository of the Kubernetes Image for the Worker to Run

+
+
Type
+

string

+
+
Default
+

''

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__WORKER_CONTAINER_REPOSITORY

+
+
+
+
+

worker_container_tag

+

The tag of the Kubernetes Image for the Worker to Run

+
+
Type
+

string

+
+
Default
+

''

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__WORKER_CONTAINER_TAG

+
+
+
+
+

worker_pod_pending_fatal_container_state_reasons

+
+
+

New in version 8.1.0.

+
+
+

If the worker pods are in a pending state due to a fatal container +state reasons, then fail the task and delete the worker pod +if delete_worker_pods is True and delete_worker_pods_on_failure is True.

+
+
Type
+

string

+
+
Default
+

CreateContainerConfigError,ErrImagePull,CreateContainerError,ImageInspectError, InvalidImageName

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__WORKER_POD_PENDING_FATAL_CONTAINER_STATE_REASONS

+
+
+
+
+

worker_pods_creation_batch_size

+

Number of Kubernetes Worker Pod creation calls per scheduler loop. +Note that the current default of “1” will only launch a single pod +per-heartbeat. It is HIGHLY recommended that users increase this +number to match the tolerance of their kubernetes cluster for +better performance.

+
+
Type
+

string

+
+
Default
+

1

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__WORKER_PODS_CREATION_BATCH_SIZE

+
+
+
+
+

worker_pods_queued_check_interval

+

How often in seconds to check for task instances stuck in “queued” status without a pod

+
+
Type
+

integer

+
+
Default
+

60

+
+
Environment Variable
+

AIRFLOW__KUBERNETES_EXECUTOR__WORKER_PODS_QUEUED_CHECK_INTERVAL

+
+
+
+
+

worker_pods_pending_timeout (Deprecated)

+
+

Deprecated since version 2.6.0: The option has been moved to scheduler.task_queued_timeout

+
+
+
+

worker_pods_pending_timeout_check_interval (Deprecated)

+
+

Deprecated since version 2.6.0: The option has been moved to scheduler.task_queued_timeout_check_interval

+
+
+
+
+

[local_kubernetes_executor]

+

This section only applies if you are using the LocalKubernetesExecutor in +[core] section above

+
+

kubernetes_queue

+

Define when to send a task to KubernetesExecutor when using LocalKubernetesExecutor. +When the queue of a task is the value of kubernetes_queue (default kubernetes), +the task is executed via KubernetesExecutor, +otherwise via LocalExecutor

+
+
Type
+

string

+
+
Default
+

kubernetes

+
+
Environment Variable
+

AIRFLOW__LOCAL_KUBERNETES_EXECUTOR__KUBERNETES_QUEUE

+
+
+
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/connections/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/connections/index.html new file mode 100644 index 00000000000..a7332c07654 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/connections/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/connections/kubernetes.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/connections/kubernetes.html new file mode 100644 index 00000000000..10e38de96aa --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/connections/kubernetes.html @@ -0,0 +1,943 @@ + + + + + + + + + + + + Kubernetes cluster Connection — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

Kubernetes cluster Connection

+

The Kubernetes cluster Connection type enables connection to a Kubernetes cluster by SparkKubernetesOperator tasks and KubernetesPodOperator tasks.

+
+

Authenticating to Kubernetes cluster

+

There are different ways to connect to Kubernetes using Airflow.

+
    +
  1. Use kube_config that reside in the default location on the machine(~/.kube/config) - just leave all fields empty

  2. +
  3. Use in_cluster config, if Airflow runs inside Kubernetes cluster take the configuration from the cluster - mark: +In cluster configuration

  4. +
  5. Use kube_config from different location - insert the path into Kube config path

  6. +
  7. Use kube_config in JSON format from connection configuration - paste kube_config into Kube config (JSON format)

  8. +
+
+
+

Default Connection IDs

+

The default connection ID is kubernetes_default .

+
+
+

Configuring the Connection

+
+
In cluster configuration

Use in cluster configuration.

+
+
Kube config path

Use custom path to kube config.

+
+
Kube config (JSON format)

Kube config +that used to connect to Kubernetes client.

+
+
Namespace

Default Kubernetes namespace for the connection.

+
+
Cluster context

When using a kube config, can specify which context to use.

+
+
Disable verify SSL

Can optionally disable SSL certificate verification. By default SSL is verified.

+
+
Disable TCP keepalive

TCP keepalive is a feature (enabled by default) that tries to keep long-running connections +alive. Set this parameter to True to disable this feature.

+
+
Xcom sidecar image

Define the image used by the PodDefaults.SIDECAR_CONTAINER (defaults to "alpine") to allow private +repositories, as well as custom image overrides.

+
+
+

Example storing connection in env var using URI format:

+
AIRFLOW_CONN_KUBERNETES_DEFAULT='kubernetes://?in_cluster=True&kube_config_path=~%2F.kube%2Fconfig&kube_config=kubeconfig+json&namespace=namespace'
+
+
+

And using JSON format:

+
AIRFLOW_CONN_KUBERNETES_DEFAULT='{"conn_type": "kubernetes", "extra": {"in_cluster": true, "kube_config_path": "~/.kube/config", "namespace": "my-namespace"}}'
+
+
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/genindex.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/genindex.html new file mode 100644 index 00000000000..93a50c2677b --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/genindex.html @@ -0,0 +1,2672 @@ + + + + + + + + + + + + Index — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ + +

Index

+ +
+ _ + | A + | B + | C + | D + | E + | F + | G + | H + | I + | J + | K + | L + | M + | N + | O + | P + | Q + | R + | S + | T + | U + | V + | W + | X + +
+

_

+ + + +
+ +

A

+ + + +
+ +

B

+ + + +
+ +

C

+ + + +
+ +

D

+ + + +
+ +

E

+ + + +
+ +

F

+ + + +
+ +

G

+ + + +
+ +

H

+ + + +
+ +

I

+ + + +
+ +

J

+ + + +
+ +

K

+ + + +
+ +

L

+ + + +
+ +

M

+ + + +
+ +

N

+ + +
+ +

O

+ + + +
+ +

P

+ + + +
+ +

Q

+ + + +
+ +

R

+ + + +
+ +

S

+ + + +
+ +

T

+ + + +
+ +

U

+ + + +
+ +

V

+ + + +
+ +

W

+ + + +
+ +

X

+ + + +
+ + + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/index.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/index.html new file mode 100644 index 00000000000..301f5fec433 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/index.html @@ -0,0 +1,960 @@ + + + + + + + + + + + + apache-airflow-providers-cncf-kubernetes — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

apache-airflow-providers-cncf-kubernetes

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

apache-airflow-providers-cncf-kubernetes package

+

Kubernetes

+

Release: 8.1.1

+
+
+

Provider package

+

This package is for the cncf.kubernetes provider. +All classes for this package are included in the airflow.providers.cncf.kubernetes python package.

+
+
+

Installation

+

You can install this package on top of an existing Airflow 2 installation via +pip install apache-airflow-providers-cncf-kubernetes. +For the minimum Airflow version supported, see Requirements below.

+
+
+

Requirements

+

The minimum Apache Airflow version supported by this provider package is 2.6.0.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

PIP package

Version required

aiofiles

>=23.2.0

apache-airflow

>=2.6.0

asgiref

>=3.5.2

cryptography

>=2.0.0

kubernetes

>=28.1.0,<=29.0.0

kubernetes_asyncio

>=28.1.0,<=29.0.0

google-re2

>=1.0

+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/installing-providers-from-sources.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/installing-providers-from-sources.html new file mode 100644 index 00000000000..544a74854cd --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/installing-providers-from-sources.html @@ -0,0 +1,996 @@ + + + + + + + + + + + + Installing from sources — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+
+
+

Installing from sources

+
+

Released packages

+

This page describes downloading and verifying apache-airflow-providers-cncf-kubernetes provider version +8.1.1 using officially released packages. +You can also install the provider package - as most Python packages - via +PyPI . +You can choose different version of the provider by selecting different version from the drop-down at +the top-left of the page.

+

The sdist and whl packages released are the “official” sources of installation that you can use if +you want to verify the origin of the packages and want to verify checksums and signatures of the packages. +The packages are available via the +Official Apache Software Foundations Downloads

+

The downloads are available at:

+ +

If you want to install from the source code, you can download from the sources link above, it will contain +a INSTALL file containing details on how you can build and install the provider.

+
+
+

Release integrity

+

PGP signatures KEYS

+

It is essential that you verify the integrity of the downloaded files using the PGP or SHA signatures. +The PGP signatures can be verified using GPG or PGP. Please download the KEYS as well as the asc +signature files for relevant distribution. It is recommended to get these files from the +main distribution directory and not from the mirrors.

+
gpg -i KEYS
+
+
+

or

+
pgpk -a KEYS
+
+
+

or

+
pgp -ka KEYS
+
+
+

To verify the binaries/sources you can download the relevant asc files for it from main +distribution directory and follow the below guide.

+
gpg --verify apache-airflow-providers-********.asc apache-airflow-*********
+
+
+

or

+
pgpv apache-airflow-providers-********.asc
+
+
+

or

+
pgp apache-airflow-providers-********.asc
+
+
+

Example:

+
$ gpg --verify apache-airflow-providers-cncf-kubernetes-8.1.1.tar.gz.asc apache-airflow-providers-cncf-kubernetes-8.1.1.tar.gz
+  gpg: Signature made Sat 11 Sep 12:49:54 2021 BST
+  gpg:                using RSA key CDE15C6E4D3A8EC4ECF4BA4B6674E08AD7DE406F
+  gpg:                issuer "kaxilnaik@apache.org"
+  gpg: Good signature from "Kaxil Naik <kaxilnaik@apache.org>" [unknown]
+  gpg:                 aka "Kaxil Naik <kaxilnaik@gmail.com>" [unknown]
+  gpg: WARNING: The key's User ID is not certified with a trusted signature!
+  gpg:          There is no indication that the signature belongs to the owner.
+  Primary key fingerprint: CDE1 5C6E 4D3A 8EC4 ECF4  BA4B 6674 E08A D7DE 406F
+
+
+

The “Good signature from …” is indication that the signatures are correct. +Do not worry about the “not certified with a trusted signature” warning. Most of the certificates used +by release managers are self signed, that’s why you get this warning. By importing the server in the +previous step and importing it via ID from KEYS page, you know that this is a valid Key already.

+

For SHA512 sum check, download the relevant sha512 and run the following:

+
shasum -a 512 apache-airflow-providers-********  | diff - apache-airflow-providers-********.sha512
+
+
+

The SHASUM of the file should match the one provided in .sha512 file.

+

Example:

+
shasum -a 512 apache-airflow-providers-cncf-kubernetes-8.1.1.tar.gz  | diff - apache-airflow-providers-cncf-kubernetes-8.1.1.tar.gz.sha512
+
+
+
+
+

Verifying PyPI releases

+

You can verify the Provider .whl packages from PyPI by locally downloading the package and signature +and SHA sum files with the script below:

+
#!/bin/bash
+PACKAGE_VERSION=8.1.1
+PACKAGE_NAME=apache-airflow-providers-cncf-kubernetes
+provider_download_dir=$(mktemp -d)
+pip download --no-deps "${PACKAGE_NAME}==${PACKAGE_VERSION}" --dest "${provider_download_dir}"
+curl "https://downloads.apache.org/airflow/providers/apache_airflow_providers_cncf_kubernetes-8.1.1-py3-none-any.whl.asc" \
+    -L -o "${provider_download_dir}/apache_airflow_providers_cncf_kubernetes-8.1.1-py3-none-any.whl.asc"
+curl "https://downloads.apache.org/airflow/providers/apache_airflow_providers_cncf_kubernetes-8.1.1-py3-none-any.whl.sha512" \
+    -L -o "${provider_download_dir}/apache_airflow_providers_cncf_kubernetes-8.1.1-py3-none-any.whl.sha512"
+echo
+echo "Please verify files downloaded to ${provider_download_dir}"
+ls -la "${provider_download_dir}"
+echo
+
+
+

Once you verify the files following the instructions from previous chapter you can remove the temporary +folder created.

+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/kubernetes_executor.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/kubernetes_executor.html new file mode 100644 index 00000000000..7406dc3eeea --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/kubernetes_executor.html @@ -0,0 +1,1350 @@ + + + + + + + + + + + + Kubernetes Executor — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

Kubernetes Executor

+
+

Note

+

As of Airflow 2.7.0, you need to install the cncf.kubernetes provider package to use +this executor. This can done by installing apache-airflow-providers-cncf-kubernetes>=7.4.0 +or by installing Airflow with the cncf.kubernetes extras: +pip install 'apache-airflow[cncf.kubernetes]'.

+
+

The Kubernetes executor runs each task instance in its own pod on a Kubernetes cluster.

+

KubernetesExecutor runs as a process in the Airflow Scheduler. The scheduler itself does +not necessarily need to be running on Kubernetes, but does need access to a Kubernetes cluster.

+

KubernetesExecutor requires a non-sqlite database in the backend.

+

When a DAG submits a task, the KubernetesExecutor requests a worker pod from the Kubernetes API. The worker pod then runs the task, reports the result, and terminates.

+_images/arch-diag-kubernetes.png +

One example of an Airflow deployment running on a distributed set of five nodes in a Kubernetes cluster is shown below.

+_images/arch-diag-kubernetes2.png +

Consistent with the regular Airflow architecture, the Workers need access to the DAG files to execute the tasks within those DAGs and interact with the Metadata repository. Also, configuration information specific to the Kubernetes Executor, such as the worker namespace and image information, needs to be specified in the Airflow Configuration file.

+

Additionally, the Kubernetes Executor enables specification of additional features on a per-task basis using the Executor config.

+_images/k8s-happy-path.png +
+

Configuration

+
+

pod_template_file

+

To customize the pod used for k8s executor worker processes, you may create a pod template file. You must provide +the path to the template file in the pod_template_file option in the kubernetes_executor section of airflow.cfg.

+

Airflow has two strict requirements for pod template files: base image and pod name.

+
+

Base image

+

A pod_template_file must have a container named base at the spec.containers[0] position, and +its image must be specified.

+

You are free to create sidecar containers after this required container, but Airflow assumes that the +airflow worker container exists at the beginning of the container array, and assumes that the +container is named base.

+
+

Note

+

Airflow may override the base container image, e.g. through pod_override +configuration; but it must be present in the template file and must not be blank.

+
+
+
+

Pod name

+

The pod’s metadata.name must be set in the template file. This field will always be set dynamically at +pod launch to guarantee uniqueness across all pods. But again, it must be included in the template, and cannot +be left blank.

+
+
+
+

Example pod templates

+

With these requirements in mind, here are some examples of basic pod_template_file YAML files.

+
+

Note

+

The examples below should work when using default Airflow configuration values. However, many custom +configuration values need to be explicitly passed to the pod via this template too. This includes, +but is not limited to, sql configuration, required Airflow connections, DAGs folder path and +logging settings. See Configuration Reference for details.

+
+

Storing DAGs in the image:

+
---
+apiVersion: v1
+kind: Pod
+metadata:
+  name: placeholder-name
+spec:
+  containers:
+    - env:
+        - name: AIRFLOW__CORE__EXECUTOR
+          value: LocalExecutor
+        # Hard Coded Airflow Envs
+        - name: AIRFLOW__CORE__FERNET_KEY
+          valueFrom:
+            secretKeyRef:
+              name: RELEASE-NAME-fernet-key
+              key: fernet-key
+        - name: AIRFLOW__DATABASE__SQL_ALCHEMY_CONN
+          valueFrom:
+            secretKeyRef:
+              name: RELEASE-NAME-airflow-metadata
+              key: connection
+        - name: AIRFLOW_CONN_AIRFLOW_DB
+          valueFrom:
+            secretKeyRef:
+              name: RELEASE-NAME-airflow-metadata
+              key: connection
+      image: dummy_image
+      imagePullPolicy: IfNotPresent
+      name: base
+      volumeMounts:
+        - mountPath: "/opt/airflow/logs"
+          name: airflow-logs
+        - mountPath: /opt/airflow/airflow.cfg
+          name: airflow-config
+          readOnly: true
+          subPath: airflow.cfg
+  restartPolicy: Never
+  securityContext:
+    runAsUser: 50000
+    fsGroup: 50000
+  serviceAccountName: "RELEASE-NAME-worker-serviceaccount"
+  volumes:
+    - emptyDir: {}
+      name: airflow-logs
+    - configMap:
+        name: RELEASE-NAME-airflow-config
+      name: airflow-config
+
+
+

Storing DAGs in a persistentVolume:

+
---
+apiVersion: v1
+kind: Pod
+metadata:
+  name: placeholder-name
+spec:
+  containers:
+    - env:
+        - name: AIRFLOW__CORE__EXECUTOR
+          value: LocalExecutor
+        # Hard Coded Airflow Envs
+        - name: AIRFLOW__CORE__FERNET_KEY
+          valueFrom:
+            secretKeyRef:
+              name: RELEASE-NAME-fernet-key
+              key: fernet-key
+        - name: AIRFLOW__DATABASE__SQL_ALCHEMY_CONN
+          valueFrom:
+            secretKeyRef:
+              name: RELEASE-NAME-airflow-metadata
+              key: connection
+        - name: AIRFLOW_CONN_AIRFLOW_DB
+          valueFrom:
+            secretKeyRef:
+              name: RELEASE-NAME-airflow-metadata
+              key: connection
+      image: dummy_image
+      imagePullPolicy: IfNotPresent
+      name: base
+      volumeMounts:
+        - mountPath: "/opt/airflow/logs"
+          name: airflow-logs
+        - mountPath: /opt/airflow/dags
+          name: airflow-dags
+          readOnly: true
+        - mountPath: /opt/airflow/airflow.cfg
+          name: airflow-config
+          readOnly: true
+          subPath: airflow.cfg
+  restartPolicy: Never
+  securityContext:
+    runAsUser: 50000
+    fsGroup: 50000
+  serviceAccountName: "RELEASE-NAME-worker-serviceaccount"
+  volumes:
+    - name: airflow-dags
+      persistentVolumeClaim:
+        claimName: RELEASE-NAME-dags
+    - emptyDir: {}
+      name: airflow-logs
+    - configMap:
+        name: RELEASE-NAME-airflow-config
+      name: airflow-config
+
+
+

Pulling DAGs from git:

+
---
+apiVersion: v1
+kind: Pod
+metadata:
+  name: dummy-name
+spec:
+  initContainers:
+    - name: git-sync
+      image: "registry.k8s.io/git-sync/git-sync:v3.6.3"
+      env:
+        - name: GIT_SYNC_BRANCH
+          value: "v2-2-stable"
+        - name: GIT_SYNC_REPO
+          value: "https://github.com/apache/airflow.git"
+        - name: GIT_SYNC_DEPTH
+          value: "1"
+        - name: GIT_SYNC_ROOT
+          value: "/git"
+        - name: GIT_SYNC_DEST
+          value: "repo"
+        - name: GIT_SYNC_ADD_USER
+          value: "true"
+        - name: GIT_SYNC_ONE_TIME
+          value: "true"
+      volumeMounts:
+        - name: airflow-dags
+          mountPath: /git
+  containers:
+    - env:
+        - name: AIRFLOW__CORE__EXECUTOR
+          value: LocalExecutor
+        # Hard Coded Airflow Envs
+        - name: AIRFLOW__CORE__FERNET_KEY
+          valueFrom:
+            secretKeyRef:
+              name: RELEASE-NAME-fernet-key
+              key: fernet-key
+        - name: AIRFLOW__DATABASE__SQL_ALCHEMY_CONN
+          valueFrom:
+            secretKeyRef:
+              name: RELEASE-NAME-airflow-metadata
+              key: connection
+        - name: AIRFLOW_CONN_AIRFLOW_DB
+          valueFrom:
+            secretKeyRef:
+              name: RELEASE-NAME-airflow-metadata
+              key: connection
+      image: dummy_image
+      imagePullPolicy: IfNotPresent
+      name: base
+      volumeMounts:
+        - mountPath: "/opt/airflow/logs"
+          name: airflow-logs
+        - mountPath: /opt/airflow/dags
+          name: airflow-dags
+          subPath: repo/airflow/example_dags
+          readOnly: false
+        - mountPath: /opt/airflow/airflow.cfg
+          name: airflow-config
+          readOnly: true
+          subPath: airflow.cfg
+  restartPolicy: Never
+  securityContext:
+    runAsUser: 50000
+    fsGroup: 50000
+  serviceAccountName: "RELEASE-NAME-worker-serviceaccount"
+  volumes:
+    - name: airflow-dags
+      emptyDir: {}
+    - name: airflow-logs
+      emptyDir: {}
+    - configMap:
+        name: RELEASE-NAME-airflow-config
+      name: airflow-config
+
+
+
+
+

pod_override

+

When using the KubernetesExecutor, Airflow offers the ability to override system defaults on a per-task basis. +To utilize this functionality, create a Kubernetes V1pod object and fill in your desired overrides. +Please note that the scheduler will override the metadata.name and containers[0].args of the V1pod before launching it.

+

To overwrite the base container of the pod launched by the KubernetesExecutor, +create a V1pod with a single container, and overwrite the fields as follows:

+
+

airflow/example_dags/example_kubernetes_executor.py[source]

+
        executor_config_volume_mount = {
+            "pod_override": k8s.V1Pod(
+                spec=k8s.V1PodSpec(
+                    containers=[
+                        k8s.V1Container(
+                            name="base",
+                            volume_mounts=[
+                                k8s.V1VolumeMount(mount_path="/foo/", name="example-kubernetes-test-volume")
+                            ],
+                        )
+                    ],
+                    volumes=[
+                        k8s.V1Volume(
+                            name="example-kubernetes-test-volume",
+                            host_path=k8s.V1HostPathVolumeSource(path="/tmp/"),
+                        )
+                    ],
+                )
+            ),
+        }
+
+        @task(executor_config=executor_config_volume_mount)
+        def test_volume_mount():
+            """
+            Tests whether the volume has been mounted.
+            """
+
+            with open("/foo/volume_mount_test.txt", "w") as foo:
+                foo.write("Hello")
+
+            return_code = os.system("cat /foo/volume_mount_test.txt")
+            if return_code != 0:
+                raise ValueError(f"Error when checking volume mount. Return code {return_code}")
+
+        volume_task = test_volume_mount()
+
+
+
+

Note that the following fields will all be extended instead of overwritten. From spec: volumes, and init_containers. From container: volume mounts, environment variables, ports, and devices.

+

To add a sidecar container to the launched pod, create a V1pod with an empty first container with the +name base and a second container containing your desired sidecar.

+
+

airflow/example_dags/example_kubernetes_executor.py[source]

+
        executor_config_sidecar = {
+            "pod_override": k8s.V1Pod(
+                spec=k8s.V1PodSpec(
+                    containers=[
+                        k8s.V1Container(
+                            name="base",
+                            volume_mounts=[k8s.V1VolumeMount(mount_path="/shared/", name="shared-empty-dir")],
+                        ),
+                        k8s.V1Container(
+                            name="sidecar",
+                            image="ubuntu",
+                            args=['echo "retrieved from mount" > /shared/test.txt'],
+                            command=["bash", "-cx"],
+                            volume_mounts=[k8s.V1VolumeMount(mount_path="/shared/", name="shared-empty-dir")],
+                        ),
+                    ],
+                    volumes=[
+                        k8s.V1Volume(name="shared-empty-dir", empty_dir=k8s.V1EmptyDirVolumeSource()),
+                    ],
+                )
+            ),
+        }
+
+        @task(executor_config=executor_config_sidecar)
+        def test_sharedvolume_mount():
+            """
+            Tests whether the volume has been mounted.
+            """
+            for i in range(5):
+                try:
+                    return_code = os.system("cat /shared/test.txt")
+                    if return_code != 0:
+                        raise ValueError(f"Error when checking volume mount. Return code {return_code}")
+                except ValueError as e:
+                    if i > 4:
+                        raise e
+
+        sidecar_task = test_sharedvolume_mount()
+
+
+
+

You can also create custom pod_template_file on a per-task basis so that you can recycle the same base values between multiple tasks. +This will replace the default pod_template_file named in the airflow.cfg and then override that template using the pod_override.

+

Here is an example of a task with both features:

+
import os
+
+import pendulum
+
+from airflow import DAG
+from airflow.decorators import task
+from airflow.example_dags.libs.helper import print_stuff
+from airflow.settings import AIRFLOW_HOME
+
+from kubernetes.client import models as k8s
+
+with DAG(
+    dag_id="example_pod_template_file",
+    schedule=None,
+    start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
+    catchup=False,
+    tags=["example3"],
+) as dag:
+    executor_config_template = {
+        "pod_template_file": os.path.join(AIRFLOW_HOME, "pod_templates/basic_template.yaml"),
+        "pod_override": k8s.V1Pod(metadata=k8s.V1ObjectMeta(labels={"release": "stable"})),
+    }
+
+    @task(executor_config=executor_config_template)
+    def task_with_template():
+        print_stuff()
+
+
+
+
+

Managing DAGs and logs

+

Use of persistent volumes is optional and depends on your configuration.

+
    +
  • Dags:

  • +
+

To get the DAGs into the workers, you can:

+
+
    +
  • Include DAGs in the image.

  • +
  • Use git-sync which, before starting the worker container, will run a git pull of the DAGs repository.

  • +
  • Storing DAGs on a persistent volume, which can be mounted on all workers.

  • +
+
+
    +
  • Logs:

  • +
+

To get task logs out of the workers, you can:

+
+
    +
  • Use a persistent volume mounted on both the webserver and workers.

  • +
  • Enable remote logging.

  • +
+
+
+

Note

+

If you don’t enable logging persistence, and if you have not enabled remote logging, logs will be lost after the worker pods shut down.

+
+
+
+
+

Comparison with CeleryExecutor

+

In contrast to CeleryExecutor, KubernetesExecutor does not require additional components such as Redis, +but does require access to Kubernetes cluster.

+

Also monitoring the Pods can be done with the built-in Kubernetes monitoring.

+

With KubernetesExecutor, each task runs in its own pod. The pod is created when the task is queued, and terminates when the task completes. +Historically, in scenarios such as burstable workloads, this presented a resource utilization advantage over CeleryExecutor, where you needed +a fixed number of long-running Celery worker pods, whether or not there were tasks to run.

+

However, the official Apache Airflow Helm chart can automatically scale celery workers down to zero based on the number of tasks in the queue, +so when using the official chart, this is no longer an advantage.

+

With Celery workers you will tend to have less task latency because the worker pod is already up and running when the task is queued. On the +other hand, because multiple tasks are running in the same pod, with Celery you may have to be more mindful about resource utilization +in your task design, particularly memory consumption.

+

One scenario where KubernetesExecutor can be helpful is if you have long-running tasks, because if you deploy while a task is running, +the task will keep running until it completes (or times out, etc). But with CeleryExecutor, provided you have set a grace period, the +task will only keep running up until the grace period has elapsed, at which time the task will be terminated. Another scenario where +KubernetesExecutor can work well is when your tasks are not very uniform with respect to resource requirements or images.

+

Finally, note that it does not have to be either-or; with CeleryKubernetesExecutor, it is possible to use both CeleryExecutor and +KubernetesExecutor simultaneously on the same cluster. CeleryKubernetesExecutor will look at a task’s queue to determine +whether to run on Celery or Kubernetes. By default, tasks are sent to Celery workers, but if you want a task to run using KubernetesExecutor, +you send it to the kubernetes queue and it will run in its own pod. And KubernetesPodOperator can be used +to similar effect, no matter what executor you are using.

+
+
+

Fault Tolerance

+
+

Tip

+

To troubleshoot issues with KubernetesExecutor, you can use airflow kubernetes generate-dag-yaml command. +This command generates the pods as they will be launched in Kubernetes and dumps them into yaml files for you to inspect.

+
+
+

Handling Worker Pod Crashes

+

When dealing with distributed systems, we need a system that assumes that any component can crash at any moment for reasons ranging from OOM errors to node upgrades.

+

In the case where a worker dies before it can report its status to the backend DB, the executor can use a Kubernetes watcher thread to discover the failed pod.

+_images/k8s-failed-pod.png +

A Kubernetes watcher is a thread that can subscribe to every change that occurs in Kubernetes’ database. It is alerted when pods start, run, end, and fail. +By monitoring this stream, the KubernetesExecutor can discover that the worker crashed and correctly report the task as failed.

+
+
+

But What About Cases Where the Scheduler Pod Crashes?

+

In cases of scheduler crashes, the scheduler will recover its state using the watcher’s resourceVersion.

+

When monitoring the Kubernetes cluster’s watcher thread, each event has a monotonically rising number called a resourceVersion. +Every time the executor reads a resourceVersion, the executor stores the latest value in the backend database. +Because the resourceVersion is stored, the scheduler can restart and continue reading the watcher stream from where it left off. +Since the tasks are run independently of the executor and report results directly to the database, scheduler failures will not lead to task failures or re-runs.

+
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/local_kubernetes_executor.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/local_kubernetes_executor.html new file mode 100644 index 00000000000..09190ca9ae0 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/local_kubernetes_executor.html @@ -0,0 +1,903 @@ + + + + + + + + + + + + LocalKubernetes Executor — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

LocalKubernetes Executor

+
+

Note

+

As of Airflow 2.7.0, you need to install the cncf.kubernetes provider package to use +this executor. This can be done by installing apache-airflow-providers-cncf-kubernetes>=7.4.0 +or by installing Airflow with the cncf.kubernetes extras: +pip install 'apache-airflow[cncf.kubernetes]'.

+
+

The LocalKubernetesExecutor allows users +to simultaneously run a LocalExecutor and a KubernetesExecutor. +An executor is chosen to run a task based on the task’s queue.

+

LocalKubernetesExecutor provides the capability of running tasks with either LocalExecutor, +which runs tasks within the scheduler service, or with KubernetesExecutor, which runs each task +in its own pod on a kubernetes cluster.

+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/objects.inv b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..75798109f9b04bac4c220936b933b50b106dc1cb GIT binary patch literal 7003 zcmV-h8>HkTAX9K?X>NERX>N99Zgg*Qc_4OWa&u{KZXhxWBOp+6Z)#;@bUGkmaA9L; zWi4T8a%OCAcP(&oZ+2;9WpZ;ZV{T(+Eo*gRWpZw1bY*i2BOq2~a&u{KZaN@1E-@}K z3L_v?Xk{RBWo=<;Ze(S0Aa78b#rNMXCQiP zX<{x4c-q~aOOxWbmVo#C3L^S0W)`@ncOAW>5~?m;nPg5v_U(>|8wz0yaAPdDWmCod z^`nQMU`VWok#kd#1^DPYvYtmr=RiMR2l%@a#rWWRC?<{@x@%{bu23AJ1d(BM{B@7L zG(f}u83GvjpP+c;Q}M_r_QK#Lip9gy$`%rw=?~^(;)h6#=zvaj#;#;!s+v=ia%GY}(^?)`AX8#+q1*s~2a z!X9t~1j97491`!N0I`N?IcJQZ{gfnuabk7DB*)ODEz?I~VtbuZ2^-qe32-X|(_J{T z`bv%wYCn%F5O~PNyiTO1^zv!xIlUC2xPq#%XjoS@VpaYG2_(F=tkcltE&OL~ptlhs zKHW>cxZ+{y3MwR2D<%I>4XHt(8BAyV`V~CQ=HO*IpUmd`@3-Z2(Y^=X46loNK7N`m zUd9ho%UQp@eV)F~r?gVR!}HVAcs{YccFP%KT4~KKSF3j>c3$7+bJn0=o+se(`73yw z%|)}8*bdxV7wF+A0Rf}~?G|~(z}t43zPB3LTAeQ7Qg;XbPEndEL;9*s3_@IaF@0AF zgCw(jnu0vnXD?E>2;?qTSWzUsglJ_zupkNkXB*-P*=ig26|06nn9E=YV3 zr(sWLy1w?{1jTzlgbC^;e0&6AiNQOtAJV=My2$=vXaxz%t^anfskvE$Xx|hHv1Yc0 zLbfxWJijcb6V26o4z7{-@v+<-E_wuBcFo`LYAIz0yBj;(W=;Q?KD;fTU%}*gJ_X;V zfA)euP5i(>&*Wka^-M0?84D?8t68v32rWbVcKuwLF0^nw6wnWt&0qUWbSI4>n7CVh zh*3P_;ShZo^dhFLiGV4YD$;Hn%ddrP4aadyt@g6lAk< zd(Q{MiUgRp2cX>@;i6a#``e4Mok#YK=CkOVG%>D1)hFP8-==R<d4!K>Tp` zVU*g!aDxCrA)$SgHgg0L%-mzMrTT}_)6ns}CF*%-m2QBS?xPQ(j`CT(C3@&R`?g3a zbYSkRt8~3a@rO}L&k4UJ3T+|LV4}1|83f~Gg<$d_wDAex4}FxmmFhzUd#Rh~*d*Jd z6yaM@kZfZFJ>-29&HlnG;B#%L{0PO#vB%2rm0Ui*eu&XQXjF4n`8ax2*4!VU@x^Hv zW_PtdfHrgw=qcTlvQVS=fY^$Te3Y@91eiHP9-tqjCk^DRBns0T<8q`p!9JAe_HW&tsu~FvGx?k88f$) z@@@W;elKyzag9$On4(i&N08j8h{Lc4h_o{$F(j6gvJJ7kyGVzicDGArB`Fr$mNI^a zege`k@dN(Wv)Cob65`*UKZ7r``S=kmmgD6cyHh=%%$Bp~IavPrBIE9F2-0Fa8>gC+ zMmU*%8NWR)>zDi`)|=)@DMuFS#gZO!#upKA_}Oa46?cob9MZnYx(P6ZdjwcVv9`l- z%sk4ErGzoEzBRJ2QV6&yN$?)v)nCZ9o0P64Eaj_Kq1Er)Lu;4@*|vdobZdK1wn^+k z>$GgAc!3VNvLWQUW&~>-@4Szm!{KqnD& zQ4bJ3?hhaM#NxhVk0q!Xj@f}|qok{&z4e?Hcbn7)Yaaz3SfMRE_&AO2W&PpOIfu~a zT^O@DGl71HV&L!L2KA0Qzxriq+hE_@y-4;6@I$)cpi2?qA>7_gp%X|8t-#HYYv>2a zvl@}4F1vcWP6InJ*_6&e31IgMi}{||PRp<6S-yf2!9OZ%C~KF@b{_#fK96~*Vs?p+ zov(bEeFa};k5lkET|B?N$^-;fr`-KQ_|>pL#^n#E>oD zp>r;z?LEP=D{(D2Fp8MZW=YZh&aMgv{j+LPY}+o%$K_i_DTA-(PLL$3qZz6_4ZD6* zcgbnjX|;i5_nA5`9fxawBi}Cge zw&IN+ZthKX7PBvlmq272`bB|CO+S;mMFHJ%fqWEHg*+8!0+EMWWPTCgY5WIxoX)>4 z|0y?o-2kml3xjA2!*ma*2(itz6*LTS!c+ASc8CG;{=_|L>DmQyZs{qra~f=z@*-zu{GX zD!oeVq>;z=tV+Hb_txP61K)%FYB8_X3hzmqDVW(6jRT^~onAJZQVlQm52ubw?R{+S zuSa3}?!6}cQ-Ex78hEtkS!jiZO+b5Fnn@+{or$!8hzihP4Wd#ibN_^!80cu8C!bdu z6Hf>=qdD^Te>y|V(w$n(xXmsWTML+)BJ$9!CI z49a^GmU60Zk&U7G;Q{Y5!zRf1EF~qtCy9>%3Yh`cR!nB&%s{g+F_waAvBw&t6Y(Kn zz=DJy0l#Zt?JL*jrf!gsB*lykpmYGmE>L64g2M2P0>6)8FRE_KVppJa14c`UQEW4E z>~A*QU#-ZnV_^&U9{UNBjtQp~kYY_)lHFw%O!}TC!77V0e|~)$KibgJYFPgoziPRE zpoi-fi3l-Y%1dO6wj5$*$ppuqRiM2m^X5VCN+>q9eXCOwH|-iu~(K@)45iSVFSOUG6col4U% z+?|RPe(YrhYiY*UxJ>~YIi$RcB05e4?gL)9d=}wp`>8|p<}4S{v~UTK z^AFI?_L{v(pA$~wSS*OwbypK|)kF&Bg(p#cVQt7{8Wh|B`l@dt&L zrBm|E^I2gG=nQp_LqCysMC_C`f-&JYs6aqlg#EZ|Jnc`TWxruLhj?5V)PvTLdBKn( zJ&)D6%w?(h~0ndPsK`Kt?ZUIcW2j0kYB>9l zXsXsr4hkLwJGEk_2}=}&7&v{0wBK8Rio$JdVtHSy(6Uj`&E3MS!FDW z@>}i>)D+IjbpSwr10b_?(p7#;*Npch5P@pg=q|a3)Ps>=J`nOVq)MB-CyNCbV#2)( zNl0)^Rl#?j=r z@!HUsMWHxi^Aq{tN`k0SoMNAClzACkwld#EZ^L{V(@&~0D?${jup-HM4!`)JPqyPC znNG_k+Eq9`R1P1Lr|jym5FZMg?}%bQ;??`C&Vn{(%&PTCe}jY z&BhNm(q71&a5bg>oRAjoOD^b_d_UoCC)giQa)SLbZQr2P1C6+Rqm1x{6*{> zENhUmVeL&ru5m!0t_+c~cLhy@GPj75lBKz^5>x#qwrN6@>$Y97DcrE_4AIt(qI{3m z6yO{uUvL^)yRXi}%(EDwFELKAivx>xHcfbRJr*Ny_!*R`%i5=k=oFX@<9zUrplj9e zc#+n!q4FZUuU1qTegrg0yiLqu`$*h3LQ#nI430N^v*@#C{*G0&)xBlv;GfN2T zTkJA=l$CgS4N@*Zmy;x0f|q7*}4UuV++ zr7hg`Jy2CbTz9~$6xO;kKBZ9B9Z)KUukMOaIb^jV(5A$2vZM7iIF=EFIOIroiTlfh z=L0l+}BE!@7Y6?7p~`zpGSOus~Knjq#wm4%jT zvcPNBK^MIK0l@%nW0X31!plMHln}LVsT$&*sR8QVPH6}H?fG+Y;%hnL;${3`GbbC0 zvVLPJq5h#qD`M`yt8?VZWojROa>3fipeABXsJcfZgQ(HL<*7}21Iw-|^a3{dxgVI? z$0|**?}xo_iFjk|dqqq=10+(do&BL9l}E zE_;4R67N?JyTj4VZc`@`IKl9JH?HEbTS<#ul|1UHh+A39=OkcHUy&Mj;|p)4Lgmw2 zwGsP!m6|`1a4U83SbNgSM3aB0f&QY@)*3ktqO@oUl4FF38C|QgwP-8^>e0IrXH>i1 zr!h>G_2vTG>m6V^ZUQrH`yJWs^}Z!*x9W$pOZN1elq7f$@aiw*CPm_J zX(ewHe5Y}_hN;L>+qf;e8WPoz}D^XJGn#eYqHOskK zxnr`$VRhR|+}Mxgm;2WR-mKUKDFfLA=!G}5v|{gxyj8Wcyzhk^Y2{ct>H~~@xC)Ry z{m!LIt5_8!t)(`_lys5Cujbm;p~YG5ZkZP&gbXCog-fU)L);dyl3ZMh@H9F3@a9~@ z11(vC6`<7?VwW-|4-|9cN+@(S-R@8(74SeR(XI^od8Xds?YYnf(wS0KP+RY6t9f7t zI&!M2(5q}|FXW6JNN1Q+QAD1;1@eUySQ6aVl4%Vka(oTi=hu^_ZcjSUl@&{x`MpeA zL#51M1GN}m(poh~3mZy=G8-tyy^&VoLI|CqOl+Tlj;qaQn&`MHJ(PB;8|b@sqEEB4 z%Pd31J2wNpw^&4)nR@sp@)d zBcte#IA|TAOjeoJ%ma4|!wm}Xrdnk2p%C?u|99X9{wPN4+Hb{2;+JJg<>53txg9>> zJ)JE*S`_`mPe|=y@sW7=1-d&Hs1!!f-J(%8m5mDa5n~@!*>TA7BamO&jEoN`j_L2X z_yDd@zzS$MN*4Z``LiSX?5KFQDyS~LX7H3LBNs3d7kE!a4unDO*9Kwr(!}r5?BZ%s z^*@QvE7db9p8vlFq5r;8AYe@{bArgCwAM;h1sYNDBO!jo#gFRZua|xmJc}>SgC(FJ zi85&>Z3ZIHMT*dY|bz(1(N z3ZWw^bW{p$D(Na(CEtT8kRRqNOoY4638zrr~)#PBPMcGh&(UlD%3s=62Htu!`=6kvAEDtA#}urHkH&Gt@7W% zCy5c#%71woH*j3lqfGOoN?S@Q{<>Q7JF6K90=4B00E7gQ`OrRM!m5&QL-0Kf z?WSPh(rU7AqzIEkpb>+Mt4qHMLU#)O`pDX^GK3Jtn(wfbdbRLutx(Mc6=CAj?~cke z*(#-wJ*vpQQf@om1a9<$GNDZ+-GatOtq6slAJWw|og;&jgdgl|4-ytGNE0?2II{vr zyugYgyueXjU|Yf))g^!@0%oiB6-?YMApU=lM(yaHJ(EA;@<&|$JLTWZp4SA+Pmj|? zD|h}{a@p6){jW*k-u2(I@W9<7cgMyY6dzzm`_< zxR6o#i%MO-11gHo-H$7Ui~av!c$I%wrzstlD**Y2qibSHo(cc%H@wQzGhU`q=4d9k zsqBc&1IhqrQc8*!_SJ1D*i)pa2&e#*88QcF*8b{Q?yYukKcsVi5U?S>{1J0+80E=9 zYX!XX13cHt9ih^XjuP8qqytCcm{a!M*{PaeSJ~* zd%)L)Q|yc4_t0iC@3cVF?n}&Whji&P&_c{{wpvJ?G**qy+!~ literal 0 HcmV?d00001 diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/operators.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/operators.html new file mode 100644 index 00000000000..8dab6f6c919 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/operators.html @@ -0,0 +1,1734 @@ + + + + + + + + + + + + KubernetesPodOperator — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+ +
+

KubernetesPodOperator

+

The KubernetesPodOperator allows +you to create and run Pods on a Kubernetes cluster.

+
+

Note

+

If you use a managed Kubernetes consider using a specialize KPO operator as it simplifies the Kubernetes authorization process :

+ +
+
+

Note

+

The Kubernetes executor is not required to use this operator.

+
+
+

How does this operator work?

+

The KubernetesPodOperator uses the +Kubernetes API to launch a pod in a Kubernetes cluster. By supplying an +image URL and a command with optional arguments, the operator uses the Kube Python Client to generate a Kubernetes API +request that dynamically launches those individual pods. +Users can specify a kubeconfig file using the config_file parameter, otherwise the operator will default +to ~/.kube/config.

+

The KubernetesPodOperator enables task-level +resource configuration and is optimal for custom Python +dependencies that are not available through the public PyPI repository. It also allows users to supply a template +YAML file using the pod_template_file parameter. +Ultimately, it allows Airflow to act a job orchestrator - no matter the language those jobs are written in.

+
+
+

Debugging KubernetesPodOperator

+

You can print out the Kubernetes manifest for the pod that would be created at runtime by calling +dry_run() on an instance of the operator.

+
from airflow.providers.cncf.kubernetes.operators.pod import KubernetesPodOperator
+
+k = KubernetesPodOperator(
+    name="hello-dry-run",
+    image="debian",
+    cmds=["bash", "-cx"],
+    arguments=["echo", "10"],
+    labels={"foo": "bar"},
+    task_id="dry_run_demo",
+    do_xcom_push=True,
+)
+
+k.dry_run()
+
+
+
+
+

Argument precedence

+

When KPO defines the pod object, there may be overlap between the KubernetesPodOperator arguments. +In general, the order of precedence is KPO field-specific arguments (e.g., secrets, cmds, affinity), more general templates full_pod_spec, pod_template_file, pod_template_dict, and followed by V1Pod, by default.

+

For namespace, if namespace is not provided via any of these methods, then we’ll first try to +get the current namespace (if the task is already running in kubernetes) and failing that we’ll use +the default namespace.

+

For pod name, if not provided explicitly, we’ll use the task_id. A random suffix is added by default so the pod +name is not generally of great consequence.

+
+
+

How to use cluster ConfigMaps, Secrets, and Volumes with Pod?

+

To add ConfigMaps, Volumes, and other Kubernetes native objects, we recommend that you import the Kubernetes model API +like this:

+
from kubernetes.client import models as k8s
+
+
+

With this API object, you can have access to all Kubernetes API objects in the form of python classes. +Using this method will ensure correctness +and type safety. While we have removed almost all Kubernetes convenience classes, we have kept the +Secret class to simplify the process of generating secret volumes/env variables.

+
+

tests/system/providers/cncf/kubernetes/example_kubernetes.py[source]

+
secret_file = Secret("volume", "/etc/sql_conn", "airflow-secrets", "sql_alchemy_conn")
+secret_env = Secret("env", "SQL_CONN", "airflow-secrets", "sql_alchemy_conn")
+secret_all_keys = Secret("env", None, "airflow-secrets-2")
+volume_mount = k8s.V1VolumeMount(
+    name="test-volume", mount_path="/root/mount_file", sub_path=None, read_only=True
+)
+
+configmaps = [
+    k8s.V1EnvFromSource(config_map_ref=k8s.V1ConfigMapEnvSource(name="test-configmap-1")),
+    k8s.V1EnvFromSource(config_map_ref=k8s.V1ConfigMapEnvSource(name="test-configmap-2")),
+]
+
+volume = k8s.V1Volume(
+    name="test-volume",
+    persistent_volume_claim=k8s.V1PersistentVolumeClaimVolumeSource(claim_name="test-volume"),
+)
+
+port = k8s.V1ContainerPort(name="http", container_port=80)
+
+init_container_volume_mounts = [
+    k8s.V1VolumeMount(mount_path="/etc/foo", name="test-volume", sub_path=None, read_only=True)
+]
+
+init_environments = [k8s.V1EnvVar(name="key1", value="value1"), k8s.V1EnvVar(name="key2", value="value2")]
+
+init_container = k8s.V1Container(
+    name="init-container",
+    image="ubuntu:16.04",
+    env=init_environments,
+    volume_mounts=init_container_volume_mounts,
+    command=["bash", "-cx"],
+    args=["echo 10"],
+)
+
+affinity = k8s.V1Affinity(
+    node_affinity=k8s.V1NodeAffinity(
+        preferred_during_scheduling_ignored_during_execution=[
+            k8s.V1PreferredSchedulingTerm(
+                weight=1,
+                preference=k8s.V1NodeSelectorTerm(
+                    match_expressions=[
+                        k8s.V1NodeSelectorRequirement(key="disktype", operator="In", values=["ssd"])
+                    ]
+                ),
+            )
+        ]
+    ),
+    pod_affinity=k8s.V1PodAffinity(
+        required_during_scheduling_ignored_during_execution=[
+            k8s.V1WeightedPodAffinityTerm(
+                weight=1,
+                pod_affinity_term=k8s.V1PodAffinityTerm(
+                    label_selector=k8s.V1LabelSelector(
+                        match_expressions=[
+                            k8s.V1LabelSelectorRequirement(key="security", operator="In", values="S1")
+                        ]
+                    ),
+                    topology_key="failure-domain.beta.kubernetes.io/zone",
+                ),
+            )
+        ]
+    ),
+)
+
+tolerations = [k8s.V1Toleration(key="key", operator="Equal", value="value")]
+
+
+
+
+
+
+

Difference between KubernetesPodOperator and Kubernetes object spec

+

The KubernetesPodOperator can be considered +a substitute for a Kubernetes object spec definition that is able +to be run in the Airflow scheduler in the DAG context. If using the operator, there is no need to create the +equivalent YAML/JSON object spec for the Pod you would like to run. +The YAML file can still be provided with the pod_template_file or even the Pod Spec constructed in Python via +the full_pod_spec parameter which requires a Kubernetes V1Pod.

+
+
+

How to use private images (container registry)?

+

By default, the KubernetesPodOperator will +look for images hosted publicly on Dockerhub. +To pull images from a private registry (such as ECR, GCR, Quay, or others), you must create a +Kubernetes Secret that represents the credentials for accessing images from the private registry that is ultimately +specified in the image_pull_secrets parameter.

+

Create the Secret using kubectl:

+
kubectl create secret docker-registry testquay \
+    --docker-server=quay.io \
+    --docker-username=<Profile name> \
+    --docker-password=<password>
+
+
+

Then use it in your pod like so:

+
+

tests/system/providers/cncf/kubernetes/example_kubernetes.py[source]

+
    quay_k8s = KubernetesPodOperator(
+        namespace="default",
+        image="quay.io/apache/bash",
+        image_pull_secrets=[k8s.V1LocalObjectReference("testquay")],
+        cmds=["bash", "-cx"],
+        arguments=["echo", "10", "echo pwd"],
+        labels={"foo": "bar"},
+        name="airflow-private-image-pod",
+        on_finish_action="delete_pod",
+        in_cluster=True,
+        task_id="task-two",
+        get_logs=True,
+    )
+
+
+
+

Also for this action you can use operator in the deferrable mode:

+
+

tests/system/providers/cncf/kubernetes/example_kubernetes_async.py[source]

+
    quay_k8s_async = KubernetesPodOperator(
+        task_id="kubernetes_private_img_task_async",
+        namespace="default",
+        image="quay.io/apache/bash",
+        image_pull_secrets=[k8s.V1LocalObjectReference("testquay")],
+        cmds=["bash", "-cx"],
+        arguments=["echo", "10", "echo pwd"],
+        labels={"foo": "bar"},
+        name="airflow-private-image-pod",
+        on_finish_action="delete_pod",
+        in_cluster=True,
+        get_logs=True,
+        deferrable=True,
+    )
+
+
+
+

Example to fetch and display container log periodically

+
+

tests/system/providers/cncf/kubernetes/example_kubernetes_async.py[source]

+
    kubernetes_task_async_log = KubernetesPodOperator(
+        task_id="kubernetes_task_async_log",
+        namespace="kubernetes_task_async_log",
+        in_cluster=False,
+        name="astro_k8s_test_pod",
+        image="ubuntu",
+        cmds=[
+            "bash",
+            "-cx",
+            (
+                "i=0; "
+                "while [ $i -ne 100 ]; "
+                "do i=$(($i+1)); "
+                "echo $i; "
+                "sleep 1; "
+                "done; "
+                "mkdir -p /airflow/xcom/; "
+                'echo \'{"message": "good afternoon!"}\' > /airflow/xcom/return.json'
+            ),
+        ],
+        do_xcom_push=True,
+        deferrable=True,
+        get_logs=True,
+        logging_interval=5,
+    )
+
+
+
+
+
+

How does XCom work?

+

The KubernetesPodOperator handles +XCom values differently than other operators. In order to pass a XCom value +from your Pod you must specify the do_xcom_push as True. This will create a sidecar container that runs +alongside the Pod. The Pod must write the XCom value into this location at the /airflow/xcom/return.json path.

+
+

Note

+

An invalid json content will fail, example echo 'hello' > /airflow/xcom/return.json fail and echo '\"hello\"' > /airflow/xcom/return.json work

+
+

See the following example on how this occurs:

+
+

tests/system/providers/cncf/kubernetes/example_kubernetes.py[source]

+
    write_xcom = KubernetesPodOperator(
+        namespace="default",
+        image="alpine",
+        cmds=["sh", "-c", "mkdir -p /airflow/xcom/;echo '[1,2,3,4]' > /airflow/xcom/return.json"],
+        name="write-xcom",
+        do_xcom_push=True,
+        on_finish_action="delete_pod",
+        in_cluster=True,
+        task_id="write-xcom",
+        get_logs=True,
+    )
+
+    pod_task_xcom_result = BashOperator(
+        bash_command="echo \"{{ task_instance.xcom_pull('write-xcom')[0] }}\"",
+        task_id="pod_task_xcom_result",
+    )
+
+    write_xcom >> pod_task_xcom_result
+
+
+
+
+

Note

+

XCOMs will be pushed only for tasks marked as State.SUCCESS.

+
+

Also for this action you can use operator in the deferrable mode:

+
+

tests/system/providers/cncf/kubernetes/example_kubernetes_async.py[source]

+
    write_xcom_async = KubernetesPodOperator(
+        task_id="kubernetes_write_xcom_task_async",
+        namespace="default",
+        image="alpine",
+        cmds=["sh", "-c", "mkdir -p /airflow/xcom/;echo '[1,2,3,4]' > /airflow/xcom/return.json"],
+        name="write-xcom",
+        do_xcom_push=True,
+        on_finish_action="delete_pod",
+        in_cluster=True,
+        get_logs=True,
+        deferrable=True,
+    )
+
+    pod_task_xcom_result_async = BashOperator(
+        task_id="pod_task_xcom_result_async",
+        bash_command="echo \"{{ task_instance.xcom_pull('write-xcom')[0] }}\"",
+    )
+
+    write_xcom_async >> pod_task_xcom_result_async
+
+
+
+
+
+

Include error message in email alert

+

Any content written to /dev/termination-log will be retrieved by Kubernetes and +included in the exception message if the task fails.

+
k = KubernetesPodOperator(
+    task_id="test_error_message",
+    image="alpine",
+    cmds=["/bin/sh"],
+    arguments=["-c", "echo hello world; echo Custom error > /dev/termination-log; exit 1;"],
+    name="test-error-message",
+    email="airflow@example.com",
+    email_on_failure=True,
+)
+
+
+

Read more on termination-log here.

+
+
+

KubernetesPodOperator callbacks

+

The KubernetesPodOperator supports different +callbacks that can be used to trigger actions during the lifecycle of the pod. In order to use them, you need to +create a subclass of KubernetesPodOperatorCallback and override +the callbacks methods you want to use. Then you can pass your callback class to the operator using the callbacks +parameter.

+

The following callbacks are supported:

+
    +
  • on_sync_client_creation: called after creating the sync client

  • +
  • on_pod_creation: called after creating the pod

  • +
  • on_pod_starting: called after the pod starts

  • +
  • on_pod_completion: called when the pod completes

  • +
  • on_pod_cleanup: called after cleaning/deleting the pod

  • +
  • on_operator_resuming: when resuming the task from deferred state

  • +
  • progress_callback: called on each line of containers logs

  • +
+

Currently, the callbacks methods are not called in the async mode, this support will be added in the future.

+
+

Example:

+
import kubernetes.client as k8s
+import kubernetes_asyncio.client as async_k8s
+
+from airflow.providers.cncf.kubernetes.operators.pod import KubernetesPodOperator
+from airflow.providers.cncf.kubernetes.callbacks import KubernetesPodOperatorCallback
+
+
+class MyCallback(KubernetesPodOperatorCallback):
+    @staticmethod
+    def on_pod_creation(*, pod: k8s.V1Pod, client: k8s.CoreV1Api, mode: str, **kwargs) -> None:
+        client.create_namespaced_service(
+            namespace=pod.metadata.namespace,
+            body=k8s.V1Service(
+                metadata=k8s.V1ObjectMeta(
+                    name=pod.metadata.name,
+                    labels=pod.metadata.labels,
+                    owner_references=[
+                        k8s.V1OwnerReference(
+                            api_version=pod.api_version,
+                            kind=pod.kind,
+                            name=pod.metadata.name,
+                            uid=pod.metadata.uid,
+                            controller=True,
+                            block_owner_deletion=True,
+                        )
+                    ],
+                ),
+                spec=k8s.V1ServiceSpec(
+                    selector=pod.metadata.labels,
+                    ports=[
+                        k8s.V1ServicePort(
+                            name="http",
+                            port=80,
+                            target_port=80,
+                        )
+                    ],
+                ),
+            ),
+        )
+
+
+k = KubernetesPodOperator(
+    task_id="test_callback",
+    image="alpine",
+    cmds=["/bin/sh"],
+    arguments=["-c", "echo hello world; echo Custom error > /dev/termination-log; exit 1;"],
+    name="test-callback",
+    callbacks=MyCallback,
+)
+
+
+
+
+ +
+
+

SparkKubernetesOperator

+

The SparkKubernetesOperator allows +you to create and run spark job on a Kubernetes cluster. It is based on spark-on-k8s-operator project.

+

This operator simplifies the interface and accepts different parameters to configure and run spark application on Kubernetes. +Similar to the KubernetesOperator, we have added the logic to wait for a job after submission, +manage error handling, retrieve logs from the driver pod and the ability to delete a spark job. +It also supports out-of-the-box Kubernetes functionalities such as handling of volumes, config maps, secrets, etc.

+
+

How does this operator work?

+

The operator initiates a Spark task by generating a SparkApplication Custom Resource Definition (CRD) within Kubernetes. +This SparkApplication task subsequently generates driver and required executor pods, using the parameters specified by the user. +The operator continuously monitors the task’s progress until it either succeeds or fails. +It retrieves logs from the driver pod and displays them in the Airflow UI.

+
+
+

Usage examples

+

In order to create a SparkKubernetesOperator task, you must provide a basic template that includes Spark configuration and +Kubernetes-related resource configuration. This template, which can be in either YAML or JSON format, serves as a +starting point for the operator. Below is a sample template that you can utilize:

+

spark_job_template.yaml

+
spark:
+  apiVersion: sparkoperator.k8s.io/v1beta2
+  version: v1beta2
+  kind: SparkApplication
+  apiGroup: sparkoperator.k8s.io
+  metadata:
+    namespace: ds
+  spec:
+    type: Python
+    pythonVersion: "3"
+    mode: cluster
+    sparkVersion: 3.0.0
+    successfulRunHistoryLimit: 1
+    restartPolicy:
+      type: Never
+    imagePullPolicy: Always
+    hadoopConf: {}
+    imagePullSecrets: []
+    dynamicAllocation:
+      enabled: false
+      initialExecutors: 1
+      minExecutors: 1
+      maxExecutors: 1
+    labels: {}
+    driver:
+      serviceAccount: default
+      container_resources:
+        gpu:
+          name: null
+          quantity: 0
+        cpu:
+          request: null
+          limit: null
+        memory:
+          request: null
+          limit: null
+    executor:
+      instances: 1
+      container_resources:
+        gpu:
+          name: null
+          quantity: 0
+        cpu:
+          request: null
+          limit: null
+        memory:
+          request: null
+          limit: null
+kubernetes:
+  # example:
+  # env_vars:
+  # - name: TEST_NAME
+  #   value: TEST_VALUE
+  env_vars: []
+
+  # example:
+  # env_from:
+  # - name: test
+  #   valueFrom:
+  #     secretKeyRef:
+  #       name: mongo-secret
+  #       key: mongo-password
+  env_from: []
+
+  # example:
+  # node_selector:
+  #   karpenter.sh/provisioner-name: spark
+  node_selector: {}
+
+  # example: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/
+  # affinity:
+  #   nodeAffinity:
+  #     requiredDuringSchedulingIgnoredDuringExecution:
+  #       nodeSelectorTerms:
+  #       - matchExpressions:
+  #         - key: beta.kubernetes.io/instance-type
+  #           operator: In
+  #           values:
+  #           - r5.xlarge
+  affinity:
+    nodeAffinity: {}
+    podAffinity: {}
+    podAntiAffinity: {}
+
+  # example: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/
+  # type: list
+  # tolerations:
+  # - key: "key1"
+  #   operator: "Equal"
+  #   value: "value1"
+  #   effect: "NoSchedule"
+  tolerations: []
+
+  # example:
+  # config_map_mounts:
+  #   snowflake-default: /mnt/tmp
+  config_map_mounts: {}
+
+  # example:
+  # volume_mounts:
+  # - name: config
+  #   mountPath: /airflow
+  volume_mounts: []
+
+  # https://kubernetes.io/docs/concepts/storage/volumes/
+  # example:
+  # volumes:
+  # - name: config
+  #   persistentVolumeClaim:
+  #     claimName: airflow
+  volumes: []
+
+  # read config map into an env variable
+  # example:
+  # from_env_config_map:
+  # - configmap_1
+  # - configmap_2
+  from_env_config_map: []
+
+  # load secret into an env variable
+  # example:
+  # from_env_secret:
+  # - secret_1
+  # - secret_2
+  from_env_secret: []
+
+  in_cluster: true
+  conn_id: kubernetes_default
+  kube_config_file: null
+  cluster_context: null
+
+
+
+

Important

+
    +
  • The template file consists of two primary categories: spark and kubernetes.

    +
      +
    • spark: This segment encompasses the task’s Spark configuration, mirroring the structure of the Spark API template.

    • +
    • kubernetes: This segment encompasses the task’s Kubernetes resource configuration, directly corresponding to the Kubernetes API Documentation. Each resource type includes an example within the template.

    • +
    +
  • +
  • The designated base image to be utilized is gcr.io/spark-operator/spark-py:v3.1.1.

  • +
  • Ensure that the Spark code is either embedded within the image, mounted using a persistentVolume, or accessible from an external location such as an S3 bucket.

  • +
+
+

Next, create the task using the following:

+
SparkKubernetesOperator(
+    task_id="spark_task",
+    image="gcr.io/spark-operator/spark-py:v3.1.1",  # OR custom image using that
+    code_path="local://path/to/spark/code.py",
+    application_file="spark_job_template.json",  # OR spark_job_template.json
+    dag=dag,
+)
+
+
+

Note: Alternatively application_file can also be a json file. see below example

+

spark_job_template.json

+
{
+  "spark": {
+    "apiVersion": "sparkoperator.k8s.io/v1beta2",
+    "version": "v1beta2",
+    "kind": "SparkApplication",
+    "apiGroup": "sparkoperator.k8s.io",
+    "metadata": {
+      "namespace": "ds"
+    },
+    "spec": {
+      "type": "Python",
+      "pythonVersion": "3",
+      "mode": "cluster",
+      "sparkVersion": "3.0.0",
+      "successfulRunHistoryLimit": 1,
+      "restartPolicy": {
+        "type": "Never"
+      },
+      "imagePullPolicy": "Always",
+      "hadoopConf": {},
+      "imagePullSecrets": [],
+      "dynamicAllocation": {
+        "enabled": false,
+        "initialExecutors": 1,
+        "minExecutors": 1,
+        "maxExecutors": 1
+      },
+      "labels": {},
+      "driver": {
+        "serviceAccount": "default",
+        "container_resources": {
+          "gpu": {
+            "name": null,
+            "quantity": 0
+          },
+          "cpu": {
+            "request": null,
+            "limit": null
+          },
+          "memory": {
+            "request": null,
+            "limit": null
+          }
+        }
+      },
+      "executor": {
+        "instances": 1,
+        "container_resources": {
+          "gpu": {
+            "name": null,
+            "quantity": 0
+          },
+          "cpu": {
+            "request": null,
+            "limit": null
+          },
+          "memory": {
+            "request": null,
+            "limit": null
+          }
+        }
+      }
+    }
+  },
+  "kubernetes": {
+    "env_vars": [],
+    "env_from": [],
+    "node_selector": {},
+    "affinity": {
+      "nodeAffinity": {},
+      "podAffinity": {},
+      "podAntiAffinity": {}
+    },
+    "tolerations": [],
+    "config_map_mounts": {},
+    "volume_mounts": [
+      {
+        "name": "config",
+        "mountPath": "/airflow"
+      }
+    ],
+    "volumes": [
+      {
+        "name": "config",
+        "persistentVolumeClaim": {
+          "claimName": "hsaljoog-airflow"
+        }
+      }
+    ],
+    "from_env_config_map": [],
+    "from_env_secret": [],
+    "in_cluster": true,
+    "conn_id": "kubernetes_default",
+    "kube_config_file": null,
+    "cluster_context": null
+  }
+}
+
+
+

An alternative method, apart from using YAML or JSON files, is to directly pass the template_spec field instead of application_file +if you prefer not to employ a file for configuration.

+
+ +
+
+

KubernetesJobOperator

+

The KubernetesJobOperator allows +you to create and run Jobs on a Kubernetes cluster.

+
+

Note

+

If you use a managed Kubernetes consider using a specialize KJO operator as it simplifies the Kubernetes authorization process :

+ +
+
+

Note

+

The Kubernetes executor is not required to use this operator.

+
+
+

How does this operator work?

+

The KubernetesJobOperator uses the +Kubernetes API to launch a job in a Kubernetes cluster. The operator uses the Kube Python Client to generate a Kubernetes API +request that dynamically launches this Job. +Users can specify a kubeconfig file using the config_file parameter, otherwise the operator will default +to ~/.kube/config. It also allows users to supply a template YAML file using the job_template_file parameter.

+
+

tests/system/providers/cncf/kubernetes/example_kubernetes_job.py[source]

+
k8s_job = KubernetesJobOperator(
+    task_id="job-task",
+    namespace=JOB_NAMESPACE,
+    image="perl:5.34.0",
+    cmds=["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"],
+    name=JOB_NAME,
+)
+
+
+
+

The KubernetesJobOperator also supports deferrable mode:

+
+

tests/system/providers/cncf/kubernetes/example_kubernetes_job.py[source]

+
k8s_job_def = KubernetesJobOperator(
+    task_id="job-task-def",
+    namespace="default",
+    image="perl:5.34.0",
+    cmds=["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"],
+    name=JOB_NAME + "-def",
+    wait_until_job_complete=True,
+    deferrable=True,
+)
+
+
+
+
+
+

Difference between KubernetesPodOperator and KubernetesJobOperator

+

The KubernetesJobOperator is operator for creating Job. +A Job creates one or more Pods and will continue to retry execution of the Pods until a specified number of them successfully terminate. +As Pods successfully complete, the Job tracks the successful completions. When a specified number of successful completions is reached, the Job is complete. +Users can limit how many times a Job retries execution using configuration parameters like activeDeadlineSeconds and backoffLimit. +Instead of template parameter for Pod creating this operator uses KubernetesPodOperator. +It means that user can use all parameters from KubernetesPodOperator in KubernetesJobOperator.

+

More information about the Jobs here: Kubernetes Job Documentation

+
+
+
+

KubernetesDeleteJobOperator

+

The KubernetesDeleteJobOperator allows +you to delete Jobs on a Kubernetes cluster.

+
+

tests/system/providers/cncf/kubernetes/example_kubernetes_job.py[source]

+
delete_job_task = KubernetesDeleteJobOperator(
+    task_id="delete_job_task",
+    name=k8s_job.output["job_name"],
+    namespace=JOB_NAMESPACE,
+    wait_for_completion=True,
+    delete_on_status="Complete",
+    poll_interval=1.0,
+)
+
+
+
+
+
+

KubernetesPatchJobOperator

+

The KubernetesPatchJobOperator allows +you to update Jobs on a Kubernetes cluster.

+
+

tests/system/providers/cncf/kubernetes/example_kubernetes_job.py[source]

+
update_job = KubernetesPatchJobOperator(
+    task_id="update-job-task",
+    namespace="default",
+    name=k8s_job.output["job_name"],
+    body={"spec": {"suspend": False}},
+)
+
+
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/output-spelling-results-apache-airflow-providers-cncf-kubernetes/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/output-spelling-results-apache-airflow-providers-cncf-kubernetes/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css new file mode 100644 index 00000000000..eb19f698afc --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/output-spelling-results-apache-airflow-providers-cncf-kubernetes/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css @@ -0,0 +1 @@ +.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative}details.sd-dropdown .sd-summary-title{font-weight:700;padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary{list-style:none;padding:1em}details.sd-dropdown summary .sd-octicon.no-title{vertical-align:middle}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown summary::-webkit-details-marker{display:none}details.sd-dropdown summary:focus{outline:none}details.sd-dropdown .sd-summary-icon{margin-right:.5em}details.sd-dropdown .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary:hover .sd-summary-up svg,details.sd-dropdown summary:hover .sd-summary-down svg{opacity:1;transform:scale(1.1)}details.sd-dropdown .sd-summary-up svg,details.sd-dropdown .sd-summary-down svg{display:block;opacity:.6}details.sd-dropdown .sd-summary-up,details.sd-dropdown .sd-summary-down{pointer-events:none;position:absolute;right:1em;top:1em}details.sd-dropdown[open]>.sd-summary-title .sd-summary-down{visibility:hidden}details.sd-dropdown:not([open])>.sd-summary-title .sd-summary-up{visibility:hidden}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #0071bc;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0060a0;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem} diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/output-spelling-results-apache-airflow-providers-cncf-kubernetes/_sphinx_design_static/design-tabs.js b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/output-spelling-results-apache-airflow-providers-cncf-kubernetes/_sphinx_design_static/design-tabs.js new file mode 100644 index 00000000000..36b38cf0d91 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/output-spelling-results-apache-airflow-providers-cncf-kubernetes/_sphinx_design_static/design-tabs.js @@ -0,0 +1,27 @@ +var sd_labels_by_text = {}; + +function ready() { + const li = document.getElementsByClassName("sd-tab-label"); + for (const label of li) { + syncId = label.getAttribute("data-sync-id"); + if (syncId) { + label.onclick = onLabelClick; + if (!sd_labels_by_text[syncId]) { + sd_labels_by_text[syncId] = []; + } + sd_labels_by_text[syncId].push(label); + } + } +} + +function onLabelClick() { + // Activate other inputs with the same sync id. + syncId = this.getAttribute("data-sync-id"); + for (label of sd_labels_by_text[syncId]) { + if (label === this) continue; + label.previousElementSibling.checked = true; + } + window.localStorage.setItem("sphinx-design-last-tab", syncId); +} + +document.addEventListener("DOMContentLoaded", ready, false); diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/py-modindex.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/py-modindex.html new file mode 100644 index 00000000000..3f58cf4a212 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/py-modindex.html @@ -0,0 +1,1147 @@ + + + + + + + + + + + + Python Module Index — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ + +

Python Module Index

+ +
+ a | + t +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
+ a
+ airflow +
    + airflow.providers.cncf.kubernetes +
    + airflow.providers.cncf.kubernetes.callbacks +
    + airflow.providers.cncf.kubernetes.decorators +
    + airflow.providers.cncf.kubernetes.decorators.kubernetes +
    + airflow.providers.cncf.kubernetes.executors +
    + airflow.providers.cncf.kubernetes.executors.kubernetes_executor +
    + airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types +
    + airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils +
    + airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor +
    + airflow.providers.cncf.kubernetes.hooks +
    + airflow.providers.cncf.kubernetes.hooks.kubernetes +
    + airflow.providers.cncf.kubernetes.k8s_model +
    + airflow.providers.cncf.kubernetes.kube_client +
    + airflow.providers.cncf.kubernetes.kube_config +
    + airflow.providers.cncf.kubernetes.kubernetes_executor_templates +
    + airflow.providers.cncf.kubernetes.kubernetes_helper_functions +
    + airflow.providers.cncf.kubernetes.operators +
    + airflow.providers.cncf.kubernetes.operators.custom_object_launcher +
    + airflow.providers.cncf.kubernetes.operators.job +
    + airflow.providers.cncf.kubernetes.operators.kubernetes_pod +
    + airflow.providers.cncf.kubernetes.operators.pod +
    + airflow.providers.cncf.kubernetes.operators.resource +
    + airflow.providers.cncf.kubernetes.operators.spark_kubernetes +
    + airflow.providers.cncf.kubernetes.pod_generator +
    + airflow.providers.cncf.kubernetes.pod_generator_deprecated +
    + airflow.providers.cncf.kubernetes.pod_launcher_deprecated +
    + airflow.providers.cncf.kubernetes.pod_template_file_examples +
    + airflow.providers.cncf.kubernetes.python_kubernetes_script +
    + airflow.providers.cncf.kubernetes.resource_convert +
    + airflow.providers.cncf.kubernetes.resource_convert.configmap +
    + airflow.providers.cncf.kubernetes.resource_convert.env_variable +
    + airflow.providers.cncf.kubernetes.resource_convert.secret +
    + airflow.providers.cncf.kubernetes.secret +
    + airflow.providers.cncf.kubernetes.sensors +
    + airflow.providers.cncf.kubernetes.sensors.spark_kubernetes +
    + airflow.providers.cncf.kubernetes.template_rendering +
    + airflow.providers.cncf.kubernetes.triggers +
    + airflow.providers.cncf.kubernetes.triggers.job +
    + airflow.providers.cncf.kubernetes.triggers.kubernetes_pod +
    + airflow.providers.cncf.kubernetes.triggers.pod +
    + airflow.providers.cncf.kubernetes.utils +
    + airflow.providers.cncf.kubernetes.utils.delete_from +
    + airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator +
    + airflow.providers.cncf.kubernetes.utils.pod_manager +
    + airflow.providers.cncf.kubernetes.utils.xcom_sidecar +
 
+ t
+ tests +
    + tests.system.providers.cncf.kubernetes +
    + tests.system.providers.cncf.kubernetes.example_kubernetes +
    + tests.system.providers.cncf.kubernetes.example_kubernetes_async +
    + tests.system.providers.cncf.kubernetes.example_kubernetes_decorator +
    + tests.system.providers.cncf.kubernetes.example_kubernetes_job +
    + tests.system.providers.cncf.kubernetes.example_kubernetes_resource +
    + tests.system.providers.cncf.kubernetes.example_spark_kubernetes +
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/search.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/search.html new file mode 100644 index 00000000000..bed95712d63 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/search.html @@ -0,0 +1,909 @@ + + + + + + + + + + + + Search — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Search

+ + + + +

+ Searching for multiple words only shows matches that contain + all words. +

+ + +
+ + + +
+ + + +
+ +
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/searchindex.js b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/searchindex.js new file mode 100644 index 00000000000..074a263b651 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"docnames": ["_api/airflow/providers/cncf/kubernetes/callbacks/index", "_api/airflow/providers/cncf/kubernetes/decorators/index", "_api/airflow/providers/cncf/kubernetes/decorators/kubernetes/index", "_api/airflow/providers/cncf/kubernetes/executors/index", "_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor/index", "_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_types/index", "_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_utils/index", "_api/airflow/providers/cncf/kubernetes/executors/local_kubernetes_executor/index", "_api/airflow/providers/cncf/kubernetes/hooks/index", "_api/airflow/providers/cncf/kubernetes/hooks/kubernetes/index", "_api/airflow/providers/cncf/kubernetes/index", "_api/airflow/providers/cncf/kubernetes/k8s_model/index", "_api/airflow/providers/cncf/kubernetes/kube_client/index", "_api/airflow/providers/cncf/kubernetes/kube_config/index", "_api/airflow/providers/cncf/kubernetes/kubernetes_executor_templates/index", "_api/airflow/providers/cncf/kubernetes/kubernetes_helper_functions/index", "_api/airflow/providers/cncf/kubernetes/operators/custom_object_launcher/index", "_api/airflow/providers/cncf/kubernetes/operators/index", "_api/airflow/providers/cncf/kubernetes/operators/job/index", "_api/airflow/providers/cncf/kubernetes/operators/kubernetes_pod/index", "_api/airflow/providers/cncf/kubernetes/operators/pod/index", "_api/airflow/providers/cncf/kubernetes/operators/resource/index", "_api/airflow/providers/cncf/kubernetes/operators/spark_kubernetes/index", "_api/airflow/providers/cncf/kubernetes/pod_generator/index", "_api/airflow/providers/cncf/kubernetes/pod_generator_deprecated/index", "_api/airflow/providers/cncf/kubernetes/pod_launcher_deprecated/index", "_api/airflow/providers/cncf/kubernetes/pod_template_file_examples/index", "_api/airflow/providers/cncf/kubernetes/python_kubernetes_script/index", "_api/airflow/providers/cncf/kubernetes/resource_convert/configmap/index", "_api/airflow/providers/cncf/kubernetes/resource_convert/env_variable/index", "_api/airflow/providers/cncf/kubernetes/resource_convert/index", "_api/airflow/providers/cncf/kubernetes/resource_convert/secret/index", "_api/airflow/providers/cncf/kubernetes/secret/index", "_api/airflow/providers/cncf/kubernetes/sensors/index", "_api/airflow/providers/cncf/kubernetes/sensors/spark_kubernetes/index", "_api/airflow/providers/cncf/kubernetes/template_rendering/index", "_api/airflow/providers/cncf/kubernetes/triggers/index", "_api/airflow/providers/cncf/kubernetes/triggers/job/index", "_api/airflow/providers/cncf/kubernetes/triggers/kubernetes_pod/index", "_api/airflow/providers/cncf/kubernetes/triggers/pod/index", "_api/airflow/providers/cncf/kubernetes/utils/delete_from/index", "_api/airflow/providers/cncf/kubernetes/utils/index", "_api/airflow/providers/cncf/kubernetes/utils/k8s_resource_iterator/index", "_api/airflow/providers/cncf/kubernetes/utils/pod_manager/index", "_api/airflow/providers/cncf/kubernetes/utils/xcom_sidecar/index", "_api/tests/system/providers/cncf/kubernetes/example_kubernetes/index", "_api/tests/system/providers/cncf/kubernetes/example_kubernetes_async/index", "_api/tests/system/providers/cncf/kubernetes/example_kubernetes_decorator/index", "_api/tests/system/providers/cncf/kubernetes/example_kubernetes_job/index", "_api/tests/system/providers/cncf/kubernetes/example_kubernetes_resource/index", "_api/tests/system/providers/cncf/kubernetes/example_spark_kubernetes/index", "_api/tests/system/providers/cncf/kubernetes/index", "changelog", "cli-ref", "commits", "configurations-ref", "connections/kubernetes", "index", "installing-providers-from-sources", "kubernetes_executor", "local_kubernetes_executor", "operators", "security"], "filenames": ["_api/airflow/providers/cncf/kubernetes/callbacks/index.rst", "_api/airflow/providers/cncf/kubernetes/decorators/index.rst", "_api/airflow/providers/cncf/kubernetes/decorators/kubernetes/index.rst", "_api/airflow/providers/cncf/kubernetes/executors/index.rst", "_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor/index.rst", "_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_types/index.rst", "_api/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_utils/index.rst", "_api/airflow/providers/cncf/kubernetes/executors/local_kubernetes_executor/index.rst", "_api/airflow/providers/cncf/kubernetes/hooks/index.rst", "_api/airflow/providers/cncf/kubernetes/hooks/kubernetes/index.rst", "_api/airflow/providers/cncf/kubernetes/index.rst", "_api/airflow/providers/cncf/kubernetes/k8s_model/index.rst", "_api/airflow/providers/cncf/kubernetes/kube_client/index.rst", "_api/airflow/providers/cncf/kubernetes/kube_config/index.rst", "_api/airflow/providers/cncf/kubernetes/kubernetes_executor_templates/index.rst", "_api/airflow/providers/cncf/kubernetes/kubernetes_helper_functions/index.rst", "_api/airflow/providers/cncf/kubernetes/operators/custom_object_launcher/index.rst", "_api/airflow/providers/cncf/kubernetes/operators/index.rst", "_api/airflow/providers/cncf/kubernetes/operators/job/index.rst", "_api/airflow/providers/cncf/kubernetes/operators/kubernetes_pod/index.rst", "_api/airflow/providers/cncf/kubernetes/operators/pod/index.rst", "_api/airflow/providers/cncf/kubernetes/operators/resource/index.rst", "_api/airflow/providers/cncf/kubernetes/operators/spark_kubernetes/index.rst", "_api/airflow/providers/cncf/kubernetes/pod_generator/index.rst", "_api/airflow/providers/cncf/kubernetes/pod_generator_deprecated/index.rst", "_api/airflow/providers/cncf/kubernetes/pod_launcher_deprecated/index.rst", "_api/airflow/providers/cncf/kubernetes/pod_template_file_examples/index.rst", "_api/airflow/providers/cncf/kubernetes/python_kubernetes_script/index.rst", "_api/airflow/providers/cncf/kubernetes/resource_convert/configmap/index.rst", "_api/airflow/providers/cncf/kubernetes/resource_convert/env_variable/index.rst", "_api/airflow/providers/cncf/kubernetes/resource_convert/index.rst", "_api/airflow/providers/cncf/kubernetes/resource_convert/secret/index.rst", "_api/airflow/providers/cncf/kubernetes/secret/index.rst", "_api/airflow/providers/cncf/kubernetes/sensors/index.rst", "_api/airflow/providers/cncf/kubernetes/sensors/spark_kubernetes/index.rst", "_api/airflow/providers/cncf/kubernetes/template_rendering/index.rst", "_api/airflow/providers/cncf/kubernetes/triggers/index.rst", "_api/airflow/providers/cncf/kubernetes/triggers/job/index.rst", "_api/airflow/providers/cncf/kubernetes/triggers/kubernetes_pod/index.rst", "_api/airflow/providers/cncf/kubernetes/triggers/pod/index.rst", "_api/airflow/providers/cncf/kubernetes/utils/delete_from/index.rst", "_api/airflow/providers/cncf/kubernetes/utils/index.rst", "_api/airflow/providers/cncf/kubernetes/utils/k8s_resource_iterator/index.rst", "_api/airflow/providers/cncf/kubernetes/utils/pod_manager/index.rst", "_api/airflow/providers/cncf/kubernetes/utils/xcom_sidecar/index.rst", "_api/tests/system/providers/cncf/kubernetes/example_kubernetes/index.rst", "_api/tests/system/providers/cncf/kubernetes/example_kubernetes_async/index.rst", "_api/tests/system/providers/cncf/kubernetes/example_kubernetes_decorator/index.rst", "_api/tests/system/providers/cncf/kubernetes/example_kubernetes_job/index.rst", "_api/tests/system/providers/cncf/kubernetes/example_kubernetes_resource/index.rst", "_api/tests/system/providers/cncf/kubernetes/example_spark_kubernetes/index.rst", "_api/tests/system/providers/cncf/kubernetes/index.rst", "changelog.rst", "cli-ref.rst", "commits.rst", "configurations-ref.rst", "connections/kubernetes.rst", "index.rst", "installing-providers-from-sources.rst", "kubernetes_executor.rst", "local_kubernetes_executor.rst", "operators.rst", "security.rst"], "titles": ["airflow.providers.cncf.kubernetes.callbacks", "airflow.providers.cncf.kubernetes.decorators", "airflow.providers.cncf.kubernetes.decorators.kubernetes", "airflow.providers.cncf.kubernetes.executors", "airflow.providers.cncf.kubernetes.executors.kubernetes_executor", "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types", "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils", "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor", "airflow.providers.cncf.kubernetes.hooks", "airflow.providers.cncf.kubernetes.hooks.kubernetes", "airflow.providers.cncf.kubernetes", "airflow.providers.cncf.kubernetes.k8s_model", "airflow.providers.cncf.kubernetes.kube_client", "airflow.providers.cncf.kubernetes.kube_config", "airflow.providers.cncf.kubernetes.kubernetes_executor_templates", "airflow.providers.cncf.kubernetes.kubernetes_helper_functions", "airflow.providers.cncf.kubernetes.operators.custom_object_launcher", "airflow.providers.cncf.kubernetes.operators", "airflow.providers.cncf.kubernetes.operators.job", "airflow.providers.cncf.kubernetes.operators.kubernetes_pod", "airflow.providers.cncf.kubernetes.operators.pod", "airflow.providers.cncf.kubernetes.operators.resource", "airflow.providers.cncf.kubernetes.operators.spark_kubernetes", "airflow.providers.cncf.kubernetes.pod_generator", "airflow.providers.cncf.kubernetes.pod_generator_deprecated", "airflow.providers.cncf.kubernetes.pod_launcher_deprecated", "airflow.providers.cncf.kubernetes.pod_template_file_examples", "airflow.providers.cncf.kubernetes.python_kubernetes_script", "airflow.providers.cncf.kubernetes.resource_convert.configmap", "airflow.providers.cncf.kubernetes.resource_convert.env_variable", "airflow.providers.cncf.kubernetes.resource_convert", "airflow.providers.cncf.kubernetes.resource_convert.secret", "airflow.providers.cncf.kubernetes.secret", "airflow.providers.cncf.kubernetes.sensors", "airflow.providers.cncf.kubernetes.sensors.spark_kubernetes", "airflow.providers.cncf.kubernetes.template_rendering", "airflow.providers.cncf.kubernetes.triggers", "airflow.providers.cncf.kubernetes.triggers.job", "airflow.providers.cncf.kubernetes.triggers.kubernetes_pod", "airflow.providers.cncf.kubernetes.triggers.pod", "airflow.providers.cncf.kubernetes.utils.delete_from", "airflow.providers.cncf.kubernetes.utils", "airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator", "airflow.providers.cncf.kubernetes.utils.pod_manager", "airflow.providers.cncf.kubernetes.utils.xcom_sidecar", "tests.system.providers.cncf.kubernetes.example_kubernetes", "tests.system.providers.cncf.kubernetes.example_kubernetes_async", "tests.system.providers.cncf.kubernetes.example_kubernetes_decorator", "tests.system.providers.cncf.kubernetes.example_kubernetes_job", "tests.system.providers.cncf.kubernetes.example_kubernetes_resource", "tests.system.providers.cncf.kubernetes.example_spark_kubernetes", "tests.system.providers.cncf.kubernetes", "Changelog", "Kubernetes Executor Commands", "Package apache-airflow-providers-cncf-kubernetes", "Configuration Reference", "Kubernetes cluster Connection", "apache-airflow-providers-cncf-kubernetes", "Installing from sources", "Kubernetes Executor", "LocalKubernetes Executor", "KubernetesPodOperator", "Releasing security patches"], "terms": {"client_typ": 0, "sourc": [0, 2, 4, 5, 6, 7, 9, 10, 11, 12, 13, 15, 16, 18, 20, 21, 22, 23, 24, 25, 27, 28, 29, 31, 32, 34, 35, 37, 39, 40, 42, 43, 44, 45, 46, 47, 48, 49, 50, 59, 61], "executionmod": 0, "base": [0, 4, 6, 7, 9, 11, 15, 16, 18, 20, 21, 22, 23, 25, 32, 34, 37, 39, 40, 43, 52, 54, 60, 61], "str": [0, 4, 6, 7, 9, 12, 15, 18, 20, 22, 23, 24, 25, 27, 28, 31, 34, 37, 39, 40, 43, 52, 54, 61], "enum": [0, 20, 39, 43, 52, 54], "execut": [0, 2, 4, 7, 9, 18, 20, 21, 22, 23, 24, 27, 39, 49, 50, 52, 53, 54, 55, 59, 61], "mode": [0, 18, 20, 52, 54, 61], "sync": [0, 4, 6, 59, 61], "async": [0, 9, 37, 39, 52, 54, 61], "kubernetespodoperatorcallback": [0, 20, 61], "kubernetespodoper": [0, 2, 18, 20, 22, 43, 45, 46, 53, 54, 56, 59], "method": [0, 4, 9, 11, 18, 20, 22, 23, 43, 54, 55, 61], "current": [0, 4, 6, 18, 20, 37, 39, 52, 55, 61], "ar": [0, 11, 12, 18, 20, 23, 52, 53, 54, 55, 56, 57, 58, 59, 61, 62], "call": [0, 6, 7, 52, 54, 55, 59, 61], "thi": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 62], "support": [0, 23, 24, 52, 54, 55, 57, 61], "ad": [0, 15, 52, 54, 55, 61], "futur": [0, 61], "static": [0, 4, 7, 9, 18, 22, 23, 24, 39, 44, 54], "on_sync_client_cr": [0, 61], "client": [0, 4, 6, 9, 11, 12, 18, 20, 22, 23, 24, 25, 28, 29, 31, 37, 39, 43, 52, 54, 55, 56, 59, 61], "kwarg": [0, 2, 6, 9, 18, 20, 21, 22, 25, 34, 40, 43, 52, 54, 55, 61], "invok": [0, 52], "after": [0, 9, 20, 52, 54, 55, 59, 61], "creat": [0, 6, 9, 18, 20, 21, 22, 23, 43, 49, 50, 52, 53, 54, 55, 58, 59, 61], "paramet": [0, 2, 4, 6, 7, 9, 11, 12, 15, 16, 18, 20, 22, 23, 24, 25, 27, 28, 29, 31, 34, 37, 39, 43, 53, 54, 55, 56, 61], "corev1api": [0, 4, 12, 43, 52, 61], "on_pod_cr": [0, 61], "pod": [0, 4, 6, 9, 10, 11, 15, 16, 17, 18, 19, 22, 23, 24, 25, 32, 34, 35, 36, 38, 43, 44, 52, 54, 55, 60], "v1pod": [0, 4, 6, 11, 20, 23, 24, 25, 43, 59, 61], "can": [0, 2, 4, 6, 7, 11, 18, 20, 23, 39, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62], "us": [0, 2, 6, 7, 9, 11, 16, 18, 19, 20, 21, 22, 23, 25, 27, 38, 39, 43, 45, 46, 48, 49, 50, 52, 53, 54, 55, 56, 58, 59, 60, 62], "": [0, 4, 7, 9, 20, 22, 23, 52, 53, 54, 55, 58, 59, 60, 61], "one": [0, 20, 23, 24, 52, 54, 58, 61], "on_pod_start": [0, 61], "when": [0, 4, 7, 18, 20, 21, 22, 23, 34, 39, 40, 43, 52, 54, 55, 56, 59, 61, 62], "start": [0, 4, 7, 9, 16, 18, 20, 25, 39, 52, 54, 55, 59, 61], "on_pod_complet": [0, 61], "complet": [0, 6, 9, 16, 18, 20, 22, 25, 34, 43, 44, 52, 59, 61], "on_pod_cleanup": [0, 61], "clean": [0, 4, 18, 20, 22, 52, 53, 54, 61], "delet": [0, 6, 9, 16, 18, 20, 21, 22, 25, 39, 40, 43, 49, 54, 55, 61], "on_operator_resum": [0, 61], "event": [0, 6, 7, 18, 20, 22, 25, 43, 52, 54, 59], "resum": [0, 20, 39, 61], "from": [0, 4, 6, 7, 9, 18, 20, 23, 24, 25, 32, 35, 39, 43, 44, 52, 53, 54, 55, 56, 59, 61, 62], "defer": [0, 4, 20, 52, 54, 61], "state": [0, 4, 20, 22, 25, 37, 39, 43, 50, 52, 53, 54, 55, 59, 61], "dict": [0, 2, 4, 6, 7, 9, 20, 22, 23, 24, 27, 28, 52, 54], "return": [0, 2, 4, 6, 7, 9, 11, 12, 15, 16, 18, 20, 22, 23, 24, 25, 28, 29, 31, 32, 40, 43, 52, 54, 59, 61], "trigger": [0, 7, 10, 20, 52, 54, 61], "progress_callback": [0, 20, 43, 52, 54, 61], "line": [0, 25, 43, 52, 54, 55, 61], "process": [0, 6, 11, 18, 20, 22, 24, 25, 52, 54, 55, 59, 61], "contain": [0, 6, 9, 20, 22, 23, 24, 25, 31, 34, 39, 43, 44, 52, 54, 55, 58, 59], "log": [0, 4, 6, 7, 9, 12, 13, 15, 16, 18, 20, 22, 23, 25, 34, 39, 43, 52, 53, 54, 55, 61], "read": [0, 4, 6, 9, 24, 25, 32, 43, 52, 54, 59, 61], "8": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 55, 56, 57, 58, 59, 60, 61, 62], "1": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 55, 56, 57, 58, 59, 60, 61, 62], "2": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 55, 56, 57, 58, 59, 60, 61, 62], "10": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 55, 56, 57, 58, 59, 60, 61, 62], "0": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 55, 56, 57, 58, 59, 60, 61, 62], "dev0": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62], "i": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62], "an": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62], "experiment": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62], "featur": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62], "kubernetes_task": 2, "python_cal": 2, "none": [2, 4, 6, 7, 9, 11, 12, 15, 16, 18, 20, 21, 22, 23, 24, 25, 32, 34, 37, 39, 40, 43, 44, 52, 54, 55, 58, 59, 61], "multiple_output": 2, "oper": [2, 4, 10, 34, 39, 50, 52, 54], "wrap": 2, "k8": [2, 6, 11, 20, 22, 23, 25, 28, 31, 34, 35, 43, 50, 52, 54, 59, 61], "also": [2, 4, 20, 22, 43, 52, 58, 59, 61], "accept": [2, 7, 61], "ani": [2, 4, 6, 7, 18, 20, 22, 23, 24, 52, 54, 55, 58, 59, 61], "argument": [2, 20, 23, 24, 37, 39, 52, 54, 55], "dockeroper": [2, 52, 54], "via": [2, 4, 7, 9, 52, 55, 57, 58, 59, 61], "reus": [2, 52, 54], "singl": [2, 20, 23, 24, 52, 54, 55, 59], "dag": [2, 15, 22, 45, 46, 48, 49, 50, 52, 54, 61], "callabl": [2, 20], "bool": [2, 4, 7, 9, 12, 15, 18, 20, 22, 23, 24, 25, 27, 34, 37, 39, 43, 54], "set": [2, 6, 7, 9, 18, 20, 39, 52, 53, 54, 55, 56, 59], "valu": [2, 7, 18, 20, 23, 24, 29, 32, 43, 52, 53, 54, 55, 59, 61], "unrol": 2, "multipl": [2, 9, 52, 54, 55, 59], "xcom": [2, 9, 20, 22, 23, 24, 43, 44, 52, 54, 56], "kei": [2, 4, 20, 29, 32, 52, 54, 58, 59, 61], "default": [2, 7, 9, 18, 20, 22, 24, 39, 40, 44, 48, 53, 54, 55, 59, 61, 62], "fals": [2, 7, 9, 18, 20, 21, 22, 23, 24, 25, 27, 34, 39, 40, 43, 52, 53, 54, 55, 59, 61], "kubernetes_executor": [3, 7, 10, 13, 59], "kubernetes_executor_typ": [3, 10], "kubernetes_executor_util": [3, 10], "local_kubernetes_executor": [3, 10], "kubernetesexecutor": [4, 6, 7, 52, 53, 54, 55, 59, 60], "For": [4, 9, 18, 20, 22, 23, 34, 40, 52, 54, 55, 57, 58, 61], "more": [4, 9, 18, 20, 21, 22, 23, 24, 34, 52, 53, 54, 55, 59, 61], "inform": [4, 9, 18, 20, 25, 43, 52, 54, 55, 59, 61, 62], "how": [4, 18, 20, 55, 58], "work": [4, 20, 52, 54, 59], "take": [4, 18, 20, 43, 52, 56], "look": [4, 18, 20, 22, 34, 52, 53, 54, 55, 59, 61], "guid": [4, 18, 20, 54, 58, 61], "base_vers": 4, "arg_namespac": 4, "arg_min_pending_minut": 4, "kubernetes_command": 4, "base_executor": [4, 7], "baseexecutor": [4, 7], "running_pod_log_lin": 4, "100": [4, 61], "supports_ad_hoc_ti_run": [4, 7], "true": [4, 7, 9, 12, 15, 18, 20, 21, 22, 23, 24, 25, 27, 39, 43, 44, 52, 54, 55, 56, 59, 61], "clear_not_launched_queued_task": [4, 52, 54], "session": [4, 9, 35], "new_sess": [4, 35], "clear": [4, 7], "task": [4, 6, 7, 9, 15, 16, 18, 20, 22, 25, 27, 39, 43, 49, 50, 52, 53, 54, 55, 56, 59, 60, 61], "were": [4, 7, 52, 53, 55, 59], "yet": 4, "launch": [4, 16, 20, 22, 24, 25, 43, 52, 53, 54, 55, 59, 61], "previous": [4, 52, 53, 54, 55], "queu": [4, 7, 52, 54, 55, 59], "end": [4, 7, 23, 24, 59], "up": [4, 18, 20, 22, 23, 24, 39, 52, 53, 54, 55, 59], "reschedul": 4, "come": [4, 54], "back": [4, 6, 20, 23, 39, 54], "same": [4, 18, 20, 21, 52, 59], "try_numb": [4, 7, 23], "befor": [4, 18, 20, 39, 52, 53, 54, 55, 59], "its": [4, 6, 9, 18, 20, 22, 27, 39, 52, 54, 59, 60], "previou": [4, 23, 24, 58], "incarn": 4, "ha": [4, 16, 18, 20, 23, 25, 39, 54, 55, 59], "been": [4, 7, 52, 54, 55, 59], "fulli": [4, 20, 23, 24], "remov": [4, 27, 52, 54, 55, 58, 61], "we": [4, 6, 7, 12, 18, 20, 22, 23, 24, 43, 49, 50, 52, 59, 61, 62], "think": 4, "It": [4, 18, 52, 55, 58, 59, 61], "possibl": [4, 39, 43, 52, 53, 54, 59], "abruptli": 4, "shut": [4, 59], "down": [4, 58, 59], "leav": [4, 18, 20, 22, 39, 43, 52, 55, 56], "non": [4, 20, 52, 54, 59], "empti": [4, 9, 20, 23, 24, 52, 54, 56, 59], "task_queu": 4, "scenario": [4, 59], "handl": [4, 40, 52, 54, 61], "normal": [4, 20, 23, 24, 52, 54], "adopt": [4, 5, 6, 7], "check": [4, 6, 7, 9, 16, 20, 22, 34, 37, 39, 43, 50, 52, 54, 55, 58, 59], "each": [4, 20, 59, 60, 61], "our": [4, 52, 54], "see": [4, 23, 39, 43, 52, 54, 55, 57, 59, 61], "correspond": [4, 52, 61], "around": 4, "match": [4, 54, 55, 58], "entri": [4, 16, 20, 54], "own": [4, 59, 60], "mark": [4, 18, 52, 54, 55, 56, 61], "re": [4, 7, 20, 52, 54, 59], "execute_async": [4, 20], "command": [4, 7, 24, 52, 54, 59, 61], "queue": [4, 6, 7, 55, 59, 60], "executor_config": [4, 6, 23, 59], "asynchron": [4, 6, 9, 18, 20, 22, 25, 43], "synchron": [4, 16, 18, 20, 22, 25, 54], "get_task_log": [4, 7], "ti": [4, 7, 52], "model": [4, 6, 7, 9, 11, 18, 20, 23, 24, 25, 28, 29, 31, 43, 55, 59, 61, 62], "taskinst": [4, 7], "A": [4, 9, 11, 15, 20, 23, 24, 54, 59, 61], "object": [4, 9, 11, 16, 18, 20, 22, 23, 27, 28, 31, 34, 43, 52, 54, 55, 59], "int": [4, 7, 15, 16, 18, 20, 22, 24, 25, 39, 43, 44], "tupl": [4, 25, 28, 43], "messag": [4, 9, 20, 25, 43, 52, 54], "type": [4, 6, 7, 9, 11, 12, 15, 18, 20, 22, 23, 25, 28, 29, 31, 43, 52, 54, 55, 56, 61], "list": [4, 7, 9, 11, 20, 23, 24, 28, 29, 31, 52, 53, 54, 55, 61], "try_adopt_task_inst": [4, 7], "try": [4, 7, 20, 22, 23, 52, 54, 59, 61], "run": [4, 6, 7, 9, 16, 18, 20, 22, 23, 24, 25, 37, 39, 43, 52, 53, 54, 55, 56, 58, 59, 60, 61], "instanc": [4, 7, 18, 20, 22, 52, 55, 59, 61], "have": [4, 7, 9, 22, 34, 52, 54, 55, 59, 61, 62], "abandon": [4, 7], "schedulerjob": [4, 7], "dy": [4, 7], "anyth": [4, 7], "schedul": [4, 6, 7, 20, 22, 24, 55, 60, 61], "becom": [4, 7], "elig": [4, 7], "unabl": [4, 7], "sequenc": [4, 7, 18, 20, 34, 52, 54], "cleanup_stuck_queued_task": [4, 7], "remnant": 4, "fail": [4, 9, 16, 18, 25, 34, 39, 43, 52, 53, 54, 55, 59, 61], "becaus": [4, 52, 59], "thei": [4, 11, 18, 20, 23, 52, 53, 59], "stuck": [4, 52, 54, 55], "get": [4, 6, 9, 18, 20, 22, 23, 24, 37, 39, 43, 52, 54, 58, 59, 61, 62], "If": [4, 6, 9, 18, 20, 22, 23, 24, 27, 39, 43, 52, 55, 58, 59, 61], "detect": [4, 52, 54], "up_for_retri": 4, "remain": [4, 18, 20, 23, 52], "retri": [4, 16, 18, 20, 22, 43, 52, 54, 55, 61], "doesn": [4, 23, 52], "t": [4, 6, 18, 20, 22, 23, 43, 52, 54, 59], "readabl": 4, "warn": [4, 20, 52, 54, 58], "adopt_launched_task": 4, "kube_cli": [4, 6, 10, 16, 25, 43], "tis_to_flush_by_kei": 4, "patch": [4, 52, 54], "exist": [4, 6, 9, 11, 18, 20, 23, 43, 52, 54, 57, 59], "so": [4, 7, 9, 11, 52, 53, 55, 59, 61, 62], "kubernetesjobwatch": [4, 6], "monitor": [4, 20, 22, 25, 43, 52, 54, 59, 61], "label": [4, 9, 18, 20, 22, 23, 24, 52, 54, 59, 61], "selector": [4, 9, 18, 24, 61], "speak": [4, 52], "kube": [4, 6, 18, 20, 43, 52, 54, 55, 56, 61], "api": [4, 9, 11, 18, 22, 23, 24, 32, 34, 43, 52, 54, 55, 59, 61], "spec": [4, 11, 16, 18, 20, 23, 25, 43, 52, 54, 59], "new": [4, 7, 20, 54, 55, 62], "taskinstancekei": [4, 7, 15], "flush": [4, 7], "aren": 4, "termin": [4, 6, 7, 20, 39, 43, 52, 54, 55, 59, 61], "do": [4, 18, 20, 22, 23, 24, 39, 44, 52, 54, 58, 61], "get_cli_command": [4, 7], "vend": [4, 52, 54], "cli": [4, 52, 53, 54], "includ": [4, 20, 54, 57, 59, 62], "overrid": [4, 18, 20, 22, 34, 52, 54, 55, 56, 59, 61], "expos": [4, 9, 20, 43], "manag": [4, 21, 23, 24, 52, 54, 58, 61], "setup": [4, 27, 52, 54], "teardown": [4, 27, 52, 54], "inspect": [4, 20, 52, 54, 59], "etc": [4, 52, 59, 61], "make": [4, 52, 53, 54], "sure": 4, "choos": [4, 7, 58], "uniqu": [4, 15, 23, 24, 54, 59], "name": [4, 9, 15, 16, 18, 20, 22, 23, 24, 27, 28, 31, 34, 37, 39, 43, 52, 54, 61], "those": [4, 52, 58, 59, 61], "avoid": [4, 11, 52, 54], "collis": 4, "kubernetesjobtyp": 5, "all_namespac": 5, "pod_executor_done_kei": 5, "airflow_executor_don": 5, "singleton": 6, "gener": [6, 15, 18, 20, 22, 23, 24, 52, 54, 59, 61], "metaclass": 6, "allow": [6, 52, 54, 55, 56, 60, 61], "implement": [6, 7, 11, 52, 54], "pattern": 6, "__call__": 6, "arg": [6, 9, 23, 24, 52, 54, 59, 61], "self": [6, 32, 40, 52, 58], "resourcevers": [6, 59], "track": [6, 9, 18, 22, 23, 61], "resource_vers": 6, "namespac": [6, 9, 16, 18, 20, 21, 22, 23, 24, 34, 37, 39, 40, 43, 52, 53, 54, 56, 59, 61], "watcher_queu": 6, "scheduler_job_id": [6, 23], "kube_config": [6, 9, 10, 52, 54, 56], "multiprocess": [6, 18, 20, 22], "util": [6, 7, 9, 10, 16, 25, 27, 52, 54, 59, 61], "logging_mixin": [6, 7, 16, 25, 43], "loggingmixin": [6, 7, 16, 25, 43], "watch": [6, 9], "job": [6, 7, 9, 10, 15, 16, 17, 22, 25, 36, 52, 54, 55, 61], "perform": [6, 18, 52, 54, 55], "process_error": 6, "error": [6, 9, 16, 23, 40, 43, 52, 54, 55, 59], "respons": [6, 7], "process_statu": [6, 25, 52], "pod_nam": [6, 9, 39, 52, 54], "statu": [6, 9, 16, 18, 20, 25, 37, 39, 43, 52, 54, 55, 59], "annot": [6, 15, 20, 22, 24, 52, 54], "airflowkubernetesschedul": 6, "result_queu": 6, "run_pod_async": [6, 25, 43, 52], "run_next": 6, "next_job": 6, "receiv": [6, 20, 52, 54, 62], "next": [6, 20, 52, 54, 61, 62], "build": [6, 15, 54, 58], "delete_pod": [6, 9, 20, 25, 39, 43, 54, 61], "doe": [6, 20, 43, 52, 55, 59], "rais": [6, 23, 52, 54, 55, 59], "patch_pod_executor_don": 6, "add": [6, 9, 20, 22, 23, 24, 44, 52, 54, 59, 61], "done": [6, 18, 20, 23, 24, 39, 44, 52, 59, 60, 61, 62], "ensur": [6, 20, 22, 43, 52, 54, 61], "don": [6, 20, 22, 43, 52, 54, 59], "continu": [6, 59, 61], "all": [6, 7, 9, 11, 20, 52, 53, 54, 55, 56, 57, 59, 61, 62], "place": [6, 23], "result": [6, 44, 52, 54, 59], "sent": [6, 7, 23, 24, 59], "process_watcher_task": 6, "watcher": [6, 52, 54, 59], "get_base_pod_from_templ": 6, "pod_template_fil": [6, 20, 23, 54, 61], "templat": [6, 18, 20, 21, 22, 27, 35, 52, 54, 61], "either": [6, 7, 18, 52, 59, 60, 61], "cfg": [6, 23, 53, 55, 59], "craft": 6, "absolut": 6, "path": [6, 9, 16, 18, 20, 22, 23, 37, 39, 53, 54, 55, 56, 59, 61], "yaml": [6, 22, 23, 35, 40, 54, 55, 59, 61], "The": [6, 9, 11, 18, 20, 23, 24, 27, 34, 37, 39, 49, 50, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62], "kubeconfig": [6, 9, 13, 20, 37, 39, 54, 56, 61], "metadata": [6, 20, 23, 24, 59, 61], "localkubernetesexecutor": [7, 55, 60], "local_executor": 7, "between": [7, 9, 18, 23, 24, 43, 59], "localexecutor": [7, 55, 59, 60], "defin": [7, 9, 32, 43, 52, 54, 55, 56, 61], "kubernetes_queu": 7, "section": [7, 24, 52, 59], "configur": [7, 9, 12, 13, 18, 20, 23, 24, 37, 39, 43, 52, 53, 54, 61], "select": [7, 58], "otherwis": [7, 9, 43, 52, 54, 55, 61], "properti": [7, 9, 16, 22, 23, 43, 52, 54], "queued_task": 7, "queuedtaskinstancetyp": 7, "local": [7, 25, 31, 52, 58, 61], "job_id": [7, 25], "inherit": [7, 52, 54], "attribut": [7, 52, 54], "sinc": [7, 20, 23, 55, 59], "realli": 7, "wrapper": 7, "custom": [7, 9, 16, 20, 52, 54, 56, 59, 61], "setter": 7, "slots_avail": 7, "number": [7, 15, 18, 22, 39, 52, 54, 55, 59, 61], "supports_pickl": 7, "supports_sentri": 7, "is_loc": 7, "is_single_thread": 7, "is_product": 7, "serve_log": 7, "change_sensor_mode_to_reschedul": 7, "callback_sink": 7, "callback": [7, 10, 20, 42, 43, 52, 54], "base_callback_sink": 7, "basecallbacksink": 7, "queue_command": 7, "task_inst": [7, 35, 61], "prioriti": [7, 20, 24], "queue_task_inst": 7, "mark_success": 7, "pickle_id": 7, "ignore_all_dep": 7, "ignore_depends_on_past": 7, "wait_for_past_depends_before_skip": 7, "ignore_task_dep": 7, "ignore_ti_st": 7, "pool": 7, "cfg_path": 7, "fetch": [7, 9, 20, 35, 52, 54, 61], "has_task": 7, "known": 7, "heartbeat": [7, 55], "get_event_buff": 7, "dag_id": [7, 15, 23, 24, 45, 46, 48, 49, 50, 53, 59], "buffer": 7, "eventbuffervaluetyp": 7, "debug_dump": 7, "debug": [7, 52, 53, 54], "dump": [7, 27, 54, 59], "sigusr2": 7, "send_callback": 7, "request": [7, 9, 23, 55, 59, 61], "send": [7, 52, 54, 55, 59], "callback_request": 7, "callbackrequest": 7, "loading_kube_config_file_resourc": 9, "load": [9, 54, 55, 61], "file": [9, 12, 16, 18, 20, 22, 23, 27, 37, 39, 40, 52, 53, 54, 55, 58, 59, 61], "job_final_status_condition_typ": 9, "job_status_condition_typ": 9, "kuberneteshook": [9, 18, 20, 21, 43, 52, 54], "conn_id": [9, 52, 61], "default_conn_nam": [9, 18, 20, 21], "client_configur": 9, "cluster_context": [9, 12, 18, 20, 22, 25, 37, 39, 52, 54, 61], "config_fil": [9, 12, 18, 20, 21, 37, 39, 52, 54, 61], "in_clust": [9, 12, 18, 20, 25, 37, 39, 52, 54, 56, 61], "disable_verify_ssl": 9, "disable_tcp_keepal": 9, "basehook": [9, 52, 54], "pod_manag": [9, 10, 16, 20, 22, 25, 41, 52, 54], "podoperatorhookprotocol": [9, 43], "connect": [9, 18, 20, 22, 34, 37, 39, 43, 52, 54, 55, 59], "cluster": [9, 12, 18, 20, 22, 34, 37, 39, 49, 50, 52, 53, 55, 59, 60], "extra": [9, 52, 54, 56, 59, 60], "field": [9, 18, 20, 23, 35, 52, 54, 56, 59, 61], "config": [9, 18, 20, 23, 28, 52, 53, 54, 55, 56, 59, 61], "kube_config_path": [9, 56], "option": [9, 20, 52, 54, 55, 56, 59, 61], "abov": [9, 55, 58], "order": [9, 18, 20, 52, 61], "onc": [9, 23, 24, 58], "present": [9, 43, 59], "about": [9, 22, 34, 52, 54, 58, 61, 62], "dictionari": [9, 18, 20, 21, 23, 28, 29, 52, 54, 55], "param": [9, 18, 20, 52, 54, 55], "pass": [9, 22, 23, 24, 52, 54, 55, 59, 61], "specifi": [9, 18, 20, 23, 24, 43, 52, 54, 56, 59, 61], "context": [9, 12, 18, 20, 21, 22, 24, 27, 34, 37, 39, 52, 54, 56, 61], "e": [9, 18, 32, 52, 59, 61], "g": [9, 18, 52, 59, 61], "you": [9, 18, 20, 22, 39, 52, 53, 55, 57, 58, 59, 60, 61, 62], "your": [9, 52, 59, 61], "within": [9, 18, 20, 22, 43, 52, 54, 59, 60, 61], "ssl": [9, 55, 56], "verif": [9, 56], "should": [9, 11, 15, 18, 20, 34, 52, 54, 55, 58, 59, 62], "disabl": [9, 52, 54, 56], "want": [9, 18, 23, 52, 58, 59, 61, 62], "keepal": [9, 55, 56], "logic": [9, 20, 23, 24, 52, 54, 61], "is_in_clust": [9, 43], "whether": [9, 12, 15, 18, 23, 24, 25, 34, 43, 52, 54, 59], "load_incluster_config": [9, 43], "conn_name_attr": 9, "kubernetes_conn_id": [9, 18, 20, 21, 22, 34, 37, 39], "kubernetes_default": [9, 22, 34, 52, 56, 61], "conn_typ": [9, 56], "hook_nam": 9, "default_namespac": 9, "classmethod": [9, 23], "get_connection_form_widget": 9, "widget": 9, "form": [9, 54, 55, 61], "get_ui_field_behaviour": 9, "behaviour": [9, 55], "get_connect": 9, "miss": [9, 52, 54], "deriv": [9, 18, 20, 21, 34], "credenti": [9, 61], "conn_extra": 9, "get_conn": 9, "api_cli": 9, "cach": [9, 20, 24, 52, 54], "core_v1_cli": [9, 43], "authent": [9, 43], "apps_v1_client": 9, "custom_object_cli": 9, "batch_v1_client": 9, "create_custom_object": 9, "group": [9, 20, 24, 34, 52, 54], "version": [9, 23, 34, 52, 54, 55, 57, 58, 61, 62], "plural": 9, "bodi": [9, 18, 21, 22, 40, 61], "resourc": [9, 10, 16, 17, 20, 24, 34, 40, 42, 43, 52, 54, 59, 61], "definit": [9, 20, 52, 54, 61], "crd": [9, 52, 54, 61], "get_custom_object": 9, "delete_custom_object": 9, "get_namespac": [9, 43, 52], "get_xcom_sidecar_container_imag": [9, 43], "sidecar": [9, 20, 23, 24, 43, 44, 52, 54, 56, 59, 61], "imag": [9, 16, 20, 22, 24, 31, 43, 52, 54, 55, 56], "get_xcom_sidecar_container_resourc": [9, 43], "get_pod_log_stream": 9, "retriev": [9, 12, 20, 43, 52, 54, 59, 61], "stream": [9, 59], "get_pod_log": 9, "get_pod": [9, 43], "get_namespaced_pod_list": 9, "label_selector": [9, 61], "kind": [9, 59, 61], "which": [9, 18, 20, 23, 49, 50, 52, 53, 56, 59, 60, 61, 62], "belong": [9, 58], "restrict": 9, "chang": [9, 54, 55, 59, 62], "describ": [9, 54, 55, 58], "them": [9, 52, 54, 55, 59, 61], "get_deployment_statu": 9, "deploy": [9, 59], "create_job": [9, 18], "v1job": [9, 18], "get_job": 9, "job_nam": [9, 37, 48, 61], "get_job_statu": 9, "wait_until_job_complet": [9, 18, 52, 54, 61], "job_poll_interv": [9, 18], "block": [9, 44, 52, 54], "until": [9, 18, 20, 39, 44, 52, 59, 61], "float": [9, 18, 20, 37, 39], "interv": [9, 18, 20, 39, 43, 53], "second": [9, 18, 20, 22, 37, 39, 43, 49, 50, 55, 59], "poll": [9, 18, 20, 37, 39], "list_jobs_all_namespac": 9, "v1joblist": 9, "list_jobs_from_namespac": 9, "dedic": 9, "is_job_complet": 9, "given": [9, 15, 18, 20, 24, 43, 52], "success": [9, 22, 52, 54, 61], "boolean": [9, 55], "indic": [9, 16, 43, 52, 58], "is_job_fail": 9, "is_job_success": 9, "successfulli": [9, 18, 52, 61], "patch_namespaced_job": 9, "updat": [9, 18, 52, 54, 61], "json": [9, 18, 20, 22, 23, 43, 52, 54, 55, 56, 61], "asynckuberneteshook": [9, 52, 54], "sdk": 9, "get_conn_extra": 9, "read_log": 9, "insid": [9, 54, 55, 56], "while": [9, 20, 22, 23, 24, 44, 52, 54, 55, 59, 61], "output": [9, 23, 24, 52, 53, 54, 61], "timestamp": [9, 25, 43], "onli": [9, 11, 18, 20, 24, 39, 52, 54, 55, 59, 61, 62], "wa": [9, 39, 52, 55], "cancel": 9, "user": [9, 52, 54, 55, 58, 60, 61], "poll_interv": [9, 18, 20, 37, 39, 52, 54, 61], "decor": [10, 27, 52, 54, 59], "executor": [10, 16, 52, 54, 55, 61], "hook": [10, 18, 20, 22, 23, 34, 37, 39, 43, 52, 54], "kubernetes_executor_templ": 10, "custom_object_launch": [10, 17], "kubernetes_pod": [10, 17, 36, 54], "spark_kubernet": [10, 17, 33, 54], "pod_template_file_exampl": 10, "resource_convert": 10, "configmap": [10, 20, 24, 30, 45, 46, 52, 54, 59], "env_vari": [10, 30], "secret": [10, 20, 24, 30, 52, 54], "sensor": [10, 54], "delete_from": [10, 41], "k8s_resource_iter": [10, 41], "xcom_sidecar": [10, 41, 52, 54], "k8s_model": [10, 32], "kubernetes_helper_funct": 10, "pod_gener": [10, 52, 54], "pod_generator_deprec": 10, "pod_launcher_deprec": 10, "python_kubernetes_script": [10, 52, 54], "template_rend": 10, "__version__": [10, 54], "interact": [11, 32, 43, 59], "k8smodel": [11, 32], "abc": [11, 20], "here": [11, 18, 23, 55, 59, 61], "backward": [11, 24, 52, 54], "compat": [11, 24, 52, 54], "reason": [11, 52, 55, 59, 62], "ideal": 11, "input": [11, 52, 54], "attach_to_pod": [11, 32], "integr": [11, 54], "abstract": 11, "attach": [11, 20, 24, 32, 44, 52], "append_to_pod": 11, "k8s_object": 11, "addit": [11, 54, 59], "potenti": 11, "commun": 12, "has_kubernet": 12, "get_kube_cli": [12, 52, 54], "core_sect": 13, "core": [13, 52, 53, 54, 55], "kubernetes_sect": 13, "logging_sect": 13, "alphanum_low": [15, 20], "pod_name_max_length": 15, "63": [15, 23, 24, 52, 54], "create_unique_id": 15, "task_id": [15, 23, 52, 54, 61], "max_length": 15, "id": [15, 18, 20, 37, 39, 52, 53, 54, 58], "max": [15, 20], "charact": [15, 20, 23, 24, 52, 54], "random": [15, 20, 52, 54, 61], "string": [15, 23, 24, 31, 52, 54, 55], "suffix": [15, 20, 61], "valid": [15, 16, 23, 24, 43, 52, 54, 58], "identifi": [15, 20, 23], "create_pod_id": 15, "annotations_to_kei": 15, "get_logs_task_metadata": 15, "annotations_for_logging_task_metadata": 15, "annotation_set": 15, "should_retry_start_spark_job": 16, "except": [16, 20, 23, 40, 43, 52, 54, 55, 59, 61, 62], "transient": [16, 43], "warrant": [16, 43], "sparkjobspec": 16, "spark": [16, 22, 34, 50, 52, 54, 61], "update_resourc": 16, "kubernetesspec": 16, "set_attribut": 16, "sparkresourc": 16, "driver": [16, 22, 34, 52, 54, 61], "driver_resourc": 16, "executor_resourc": 16, "convert_resourc": 16, "customobjectstatu": 16, "submit": [16, 50, 59], "succeed": [16, 20, 25, 39, 43, 53], "customobjectlaunch": [16, 22], "custom_obj_api": [16, 22], "template_bodi": [16, 22, 52, 54], "get_bodi": 16, "start_spark_job": 16, "code_path": [16, 22, 61], "startup_timeout": [16, 25, 39, 43], "600": [16, 22], "wait": [16, 18, 25, 39, 43, 52, 54, 61], "py": [16, 52, 54, 55, 59, 61], "python": [16, 18, 23, 27, 52, 54, 55, 57, 58, 61], "jar": 16, "scala": 16, "timeout": [16, 20, 22, 25, 39, 43, 52, 54], "startup": [16, 20, 22, 25, 43, 52, 54], "pend": [16, 25, 43, 52, 53, 55], "too": [16, 25, 43, 52, 54, 59], "long": [16, 25, 43, 56, 59], "spark_job_not_run": 16, "spark_obj_spec": 16, "test": [16, 25, 52, 54, 59, 61, 62], "check_pod_start_failur": 16, "delete_spark_job": 16, "spark_job_nam": 16, "kubernetesjoboper": [18, 48, 52, 54], "job_template_fil": [18, 61], "full_job_spec": 18, "backoff_limit": 18, "completion_mod": 18, "manual_selector": 18, "parallel": 18, "suspend": [18, 54, 61], "ttl_seconds_after_finish": 18, "deferr": [18, 20, 22, 52, 54, 61], "conf": [18, 20, 52, 54], "getboolean": [18, 20], "default_deferr": [18, 20, 52, 54], "fallback": [18, 20], "googl": [18, 20, 57, 61], "engin": [18, 20, 61], "consid": [18, 20, 52, 54, 55, 61], "gkestartjoboper": [18, 52, 54, 61], "simplifi": [18, 20, 52, 54, 61], "author": [18, 20, 61], "jodspec": 18, "6": [18, 55, 57, 59], "completionmod": 18, "nonindex": 18, "index": 18, "desir": [18, 59], "finish": [18, 20, 43], "manualselector": 18, "control": [18, 52, 55, 61], "maximum": [18, 23, 55], "time": [18, 20, 39, 43, 53, 55, 59, 61], "v1labelselector": [18, 61], "v1jobspec": 18, "ttlsecondsafterfinish": 18, "limit": [18, 52, 54, 59, 61], "lifetim": 18, "note": [18, 54, 55, 59, 61], "must": [18, 20, 23, 24, 52, 59, 61], "template_field": [18, 20, 22, 34, 52, 54], "job_request_obj": 18, "execute_deferr": 18, "execute_complet": [18, 20, 52, 54], "deserialize_job_template_fil": 18, "unfortun": [18, 23], "need": [18, 20, 22, 23, 24, 52, 54, 55, 59, 60, 61], "access": [18, 23, 59, 61], "privat": [18, 23, 56], "_apiclient__deserialize_model": [18, 23], "issu": [18, 23, 52, 54, 59], "http": [18, 20, 22, 23, 34, 39, 43, 50, 55, 58, 59, 61], "github": [18, 22, 23, 34, 50, 55, 59], "com": [18, 20, 22, 23, 34, 50, 55, 58, 59, 61], "977": [18, 23], "on_kil": [18, 20, 22, 54], "subprocess": [18, 20, 22], "kill": [18, 20, 22, 43, 52], "thread": [18, 20, 22, 59], "ghost": [18, 20, 22], "behind": [18, 20, 22], "build_job_request_obj": 18, "full": [18, 20, 23, 24, 52, 54], "other": [18, 20, 32, 43, 52, 54, 59, 61], "preced": [18, 20], "reconcile_job": 18, "base_job": 18, "client_job": 18, "merg": [18, 23], "overwritten": [18, 23, 59], "recurs": [18, 23], "certain": [18, 23, 52], "some": [18, 23, 52, 54, 59], "concaten": [18, 23, 52], "reconcile_job_spec": 18, "base_spec": [18, 23], "client_spec": [18, 23], "jobspec": 18, "kubernetesdeletejoboper": [18, 52, 54], "delete_on_statu": [18, 52, 54, 61], "wait_for_complet": [18, 61], "baseoper": [18, 20], "point": [18, 20, 37, 39, 54, 61], "ignor": [18, 20, 52, 54], "condit": [18, 52, 54], "depend": [18, 52, 54, 59, 61, 62], "regardless": [18, 20, 39], "render": [18, 21, 27, 35, 52, 54], "jinja": [18, 21, 27, 52, 54], "refer": [18, 21, 22, 31, 34, 54, 59], "get_template_context": [18, 21], "kubernetespatchjoboper": [18, 52, 54], "io": [18, 34, 39, 43, 52, 54, 59, 61], "doc": [18, 22, 23, 34, 39, 43, 52, 54, 61], "v1": [18, 59], "25": [18, 54], "batch": [18, 54], "modul": [19, 38, 52, 54], "deprec": [19, 20, 25, 38, 39, 54], "pleas": [19, 20, 25, 38, 52, 58, 59], "instead": [19, 20, 25, 38, 39, 52, 54, 59, 61], "kube_config_env_var": 20, "podeventtyp": 20, "emit": 20, "podreattachfailur": 20, "airflowexcept": [20, 23, 43, 52, 54], "expect": [20, 43, 52, 54, 55], "abl": [20, 61], "find": [20, 52, 54], "cannot": [20, 59], "random_name_suffix": 20, "cmd": [20, 24, 54, 61], "port": [20, 24, 45, 46, 59, 61], "volume_mount": [20, 24, 44, 45, 46, 52, 54, 59, 61], "volum": [20, 24, 28, 32, 44, 45, 46, 52, 54, 59], "env_var": [20, 29, 52, 54, 61], "env_from": [20, 61], "reattach_on_restart": [20, 22, 52, 54], "startup_timeout_second": [20, 22], "120": [20, 25, 39, 43, 55], "startup_check_interval_second": [20, 52, 54], "5": [20, 34, 39, 53, 55, 57, 59, 61], "get_log": [20, 22, 25, 39, 52, 54, 61], "container_log": [20, 52, 54], "base_container_nam": [20, 22, 39], "image_pull_polici": [20, 24, 52, 54], "container_resourc": [20, 52, 54, 61], "affin": [20, 24, 45, 46, 52, 54, 61], "node_selector": [20, 24, 52, 54, 61], "image_pull_secret": [20, 24, 31, 61], "service_account_nam": [20, 24], "hostnetwork": [20, 24], "host_alias": 20, "toler": [20, 24, 45, 46, 55, 61], "security_context": [20, 24], "container_security_context": [20, 52, 54], "dnspolici": [20, 24], "dns_config": 20, "hostnam": 20, "subdomain": 20, "schedulernam": [20, 24], "full_pod_spec": [20, 54, 61], "init_contain": [20, 24, 45, 46, 59, 61], "log_events_on_failur": [20, 22], "do_xcom_push": [20, 22, 52, 54, 61], "pod_template_dict": [20, 52, 54, 61], "priority_class_nam": [20, 24], "pod_runtime_info_env": [20, 52], "termination_grace_period": 20, "skip_on_exit_cod": [20, 52, 54], "log_pod_spec_on_failur": 20, "on_finish_act": [20, 39, 52, 54, 61], "is_delete_operator_pod": [20, 54], "termination_message_polici": [20, 52, 54], "active_deadline_second": [20, 52, 54], "logging_interv": [20, 39, 52, 61], "gkestartpodoper": [20, 43, 54, 61], "docker": [20, 22, 24, 52, 54, 61], "wish": [20, 22], "hub": [20, 22], "qualifi": 20, "url": [20, 61], "repositori": [20, 55, 56, 59, 61], "plu": 20, "dn": 20, "1123": 20, "z0": [20, 23, 24], "9": [20, 23, 24], "entrypoint": 20, "v1containerport": [20, 24, 61], "v1volumemount": [20, 24, 28, 52, 54, 59, 61], "volumemount": [20, 52, 54, 59], "v1volum": [20, 24, 28, 59, 61], "persistentvolum": [20, 59, 61], "v1envvar": [20, 29, 54, 61], "environ": [20, 24, 27, 32, 52, 54, 55, 59], "variabl": [20, 24, 27, 52, 54, 55, 59, 61], "initi": [20, 52, 61], "v1envfromsourc": [20, 28, 31, 61], "popul": 20, "inject": 20, "var": [20, 52, 56], "worker": [20, 23, 24, 37, 39, 52, 54, 55], "di": [20, 22, 59], "reattach": [20, 22, 52, 54], "dure": [20, 23, 40, 61], "alwai": [20, 24, 52, 54, 59, 61, 62], "appli": [20, 23, 24, 52, 54, 55], "alreadi": [20, 22, 39, 50, 52, 54, 58, 59, 61], "stdout": [20, 22, 39], "iter": 20, "typing_extens": [20, 52, 54], "liter": [20, 52, 54], "whose": 20, "publish": [20, 62], "conjunct": 20, "polici": [20, 24, 52, 62], "pull": [20, 24, 31, 44, 52, 54, 59, 61], "larg": [20, 52, 54], "rang": [20, 59], "data": [20, 40, 44, 54], "permit": [20, 23], "v1resourcerequir": [20, 24, 52], "v1affin": [20, 61], "rule": [20, 24, 54, 62], "v1localobjectrefer": [20, 31, 61], "than": [20, 23, 24, 43, 52, 54, 61], "requir": [20, 24, 50, 52, 54, 55, 59, 61, 62], "comma": [20, 24, 31], "separ": [20, 23, 24, 31, 52, 54, 62], "secret_a": [20, 24], "secret_b": [20, 24], "servic": [20, 55, 60], "account": [20, 55], "enabl": [20, 24, 43, 52, 54, 55, 56, 59, 61], "host": [20, 24, 61], "network": [20, 24], "v1hostalia": 20, "alias": 20, "v1toler": [20, 61], "v1podsecuritycontext": [20, 24], "secur": [20, 24, 54, 61], "podsecuritycontext": 20, "v1securitycontext": 20, "v1poddnsconfig": 20, "ip": 20, "address": 20, "search": [20, 52], "podspec": [20, 23], "v1contain": [20, 23, 24, 59, 61], "init": [20, 24, 61], "failur": [20, 22, 52, 54, 59, 61], "occur": [20, 22, 40, 52, 59, 61], "push": [20, 22, 52, 54, 61], "grace": [20, 59], "period": [20, 37, 39, 52, 54, 59, 61], "ui": [20, 61], "map": [20, 28, 52, 54, 61], "collect": 20, "target": 20, "repres": [20, 23, 24, 61], "pair": 20, "extend": [20, 43, 59], "exit": [20, 24, 43, 44, 52, 54, 61], "code": [20, 22, 27, 52, 54, 58, 59, 61], "skip": [20, 52, 54, 55], "zero": [20, 59], "treat": 20, "appear": 20, "part": [20, 52, 53, 54], "consult": 20, "specif": [20, 23, 24, 52, 54, 59, 61], "what": [20, 22, 39, 52], "reach": [20, 22, 39, 43, 61], "final": [20, 22, 25, 39, 43, 50, 52, 54, 59], "interrupt": [20, 22, 39, 52, 54], "delete_succeeded_pod": [20, 39, 43], "keep_pod": [20, 39, 43], "keep": [20, 22, 39, 52, 54, 56, 59], "translat": 20, "v1podspec": [20, 23, 59], "differ": [20, 23, 24, 52, 56, 58], "step": [20, 52, 54, 58], "function": [20, 52, 54, 59, 61], "latest": [20, 39, 52, 54, 59, 62], "visibl": 20, "istio_container_nam": 20, "istio": [20, 43, 52, 54], "proxi": [20, 52], "kill_istio_proxy_success_msg": 20, "200": 20, "pod_checked_kei": 20, "already_check": 20, "post_termination_timeout": [20, 43], "template_fields_render": [20, 22], "find_pod": [20, 52], "exclude_check": 20, "get_or_create_pod": [20, 52], "pod_request_obj": 20, "await_pod_start": [20, 43, 52, 54], "extract_xcom": [20, 23, 24, 25, 43, 52], "execute_sync": 20, "invoke_defer_method": 20, "last_log_tim": [20, 39, 43], "redefin": 20, "being": [20, 23, 24, 52, 54], "child": [20, 52, 54], "trigger_reentri": 20, "ll": [20, 52, 61], "just": [20, 56], "could": 20, "still": [20, 52, 54, 61], "grab": 20, "again": [20, 52, 59], "write_log": 20, "follow": [20, 23, 24, 43, 52, 54, 58, 59, 61, 62], "since_tim": 20, "post_complete_act": 20, "remote_pod": 20, "action": [20, 43, 61], "deferrable_execut": 20, "cleanup": [20, 52, 54], "is_istio_en": 20, "kill_istio_sidecar": 20, "process_pod_delet": [20, 22, 52], "rerais": [20, 22], "patch_already_check": [20, 22, 52], "build_pod_request_obj": [20, 52, 54], "dry_run": [20, 22, 52, 54, 61], "print": [20, 22, 39, 52, 54, 61], "out": [20, 22, 52, 54, 55, 59, 61, 62], "would": [20, 22, 27, 52, 61], "isn": [20, 52], "exclud": [20, 54], "element": [20, 52, 54], "kubernetescreateresourceoper": [21, 49, 52, 54], "yaml_conf": 21, "yaml_conf_fil": 21, "custom_resource_definit": [21, 22, 52], "kubernetesresourcebaseoper": [21, 52, 54], "create_custom_from_yaml_object": 21, "kubernetesdeleteresourceoper": [21, 49, 52, 54], "delete_custom_from_yaml_object": 21, "sparkkubernetesoper": [22, 50, 52, 54, 56], "application_fil": [22, 52, 54, 61], "template_spec": [22, 61], "success_run_history_limit": 22, "delete_on_termin": 22, "sparkappl": [22, 34, 50, 61], "detail": [22, 23, 34, 54, 58, 59], "applic": [22, 34, 50, 52, 54, 61], "googlecloudplatform": [22, 34, 50], "blob": [22, 23, 34, 55], "v1beta2": [22, 34, 61], "3": [22, 23, 55, 57, 59, 61], "md": [22, 23, 34], "filepath": 22, "put": 22, "past": [22, 56], "template_ext": 22, "yml": 22, "ui_color": 22, "f4a460": 22, "manage_template_spec": 22, "create_job_nam": 22, "create_labels_for_pod": [22, 52], "include_try_numb": [22, 52], "case": [22, 52, 54, 62], "crash": [22, 52, 54], "find_spark_job": 22, "get_or_create_spark_crd": 22, "launcher": [22, 52, 54], "interfac": [23, 24, 61], "advantag": [23, 24, 59], "serial": [23, 24, 37, 39], "written": [23, 24, 61], "max_label_len": [23, 24], "podmutationhookexcept": 23, "happen": 23, "mutat": [23, 52], "podreconciliationerror": 23, "encount": 23, "make_safe_label_valu": [23, 24], "length": [23, 24, 52, 54], "less": [23, 24, 59], "begin": [23, 24, 59], "alphanumer": [23, 24], "9a": [23, 24], "z": [23, 24], "dash": [23, 24], "underscor": [23, 24], "_": [23, 24], "dot": [23, 24], "greater": [23, 24], "char": [23, 24], "made": [23, 24, 58], "safe": [23, 24], "wai": [23, 24, 52, 56], "origin": [23, 24, 52, 54, 58], "truncat": [23, 24], "53": [23, 24], "append": [23, 24, 34], "hash": [23, 24, 54], "datetime_to_label_safe_datestr": 23, "datetime_obj": 23, "transform": 23, "datetim": [23, 39, 43, 52, 54, 59], "like": [23, 52, 55, 61], "iso": 23, "format": [23, 39, 54, 55, 56, 61], "let": [23, 54], "replac": [23, 27, 52, 54, 59], "label_safe_datestring_to_datetim": 23, "podgener": [23, 24], "first": [23, 24, 49, 50, 52, 54, 59, 61], "mutual": [23, 24], "exclus": [23, 24], "bring": [23, 24], "gen_pod": [23, 24], "add_xcom_sidecar": [23, 44], "from_obj": [23, 24], "obj": [23, 24], "convert": [23, 24, 27, 28, 29, 31, 32, 52, 54], "from_legacy_obj": 23, "reconcile_pod": 23, "base_pod": 23, "client_pod": 23, "reconcile_metadata": 23, "base_meta": 23, "client_meta": 23, "reconcile_spec": 23, "reconcile_contain": 23, "base_contain": 23, "client_contain": 23, "over": [23, 59], "construct_pod": 23, "pod_id": 23, "kube_imag": 23, "date": [23, 53], "pod_override_object": [23, 52, 54], "base_worker_pod": 23, "run_id": [23, 52, 54], "map_index": [23, 52, 54], "with_mutation_hook": 23, "construct": [23, 52, 61], "gather": 23, "consolid": [23, 52, 54], "dynam": [23, 52, 54, 59, 61], "serialize_pod": 23, "serializ": 23, "deserialize_model_fil": 23, "deserialize_model_dict": 23, "pod_dict": 23, "deseri": 23, "de": 23, "make_unique_pod_id": [23, 24], "consist": [23, 59, 61], "lowercas": 23, "rfc1035": 23, "rfc1123": 23, "253": [23, 24], "regex": [23, 24], "releas": [23, 52, 54, 57, 59], "design": [23, 52, 54, 59, 61], "appropri": [23, 24], "merge_object": 23, "base_obj": 23, "client_obj": 23, "extend_object_field": 23, "field_nam": 23, "copi": 23, "modifi": [23, 54], "two": [23, 49, 50, 52, 59, 61], "max_pod_id_len": 24, "poddefault": [24, 44, 56], "xcom_mount_path": [24, 44], "sidecar_container_nam": [24, 44], "xcom_cmd": [24, 44], "trap": [24, 44], "sleep": [24, 44, 61], "30": [24, 53, 54, 55], "sidecar_contain": [24, 44, 56], "env": [24, 52, 56, 59, 61], "restart_polici": 24, "mount": [24, 28, 59, 61], "node": [24, 59, 61], "restart": [24, 59], "ident": 24, "ref": [24, 54], "configmap_a": 24, "configmap_b": 24, "path_or_str": 24, "add_sidecar": 24, "podstatu": [25, 52], "podlaunch": [25, 54], "podmanag": [25, 43, 52, 54], "start_pod": [25, 52], "v1_pod": [25, 43], "monitor_pod": [25, 52], "parse_log_lin": [25, 43], "pars": [25, 43, 52, 54], "pod_not_start": [25, 52], "pod_is_run": [25, 52], "base_container_is_run": 25, "read_pod_log": [25, 43, 52, 54], "tail_lin": [25, 43], "since_second": [25, 43], "read_pod_ev": [25, 43, 52], "read_pod": [25, 43], "remove_task_decor": 27, "python_sourc": 27, "task_decorator_nam": 27, "similar": [27, 52, 54, 55, 59, 61], "well": [27, 56, 58, 59], "write_python_script": 27, "jinja_context": 27, "filenam": 27, "render_template_as_native_obj": 27, "script": [27, 54, 58], "virtual": 27, "unpack": [27, 52, 54], "placehold": [27, 59], "nativ": [27, 54, 61], "convert_configmap": 28, "configmap_nam": 28, "convert_configmap_to_volum": 28, "configmap_info": 28, "config_map_nam": 28, "mount_path": [28, 59, 61], "convert_env_var": [29, 54], "convert_secret": 31, "secret_nam": 31, "convert_image_pull_secret": 31, "deploy_typ": 32, "deploy_target": 32, "item": [32, 52, 54], "to_env_secret": 32, "store": [32, 56, 59], "to_env_from_secret": 32, "to_volume_secret": 32, "__eq__": 32, "__repr__": 32, "repr": 32, "sparkkubernetessensor": [34, 50, 52, 54], "application_nam": 34, "attach_log": 34, "container_nam": [34, 43, 52, 54], "api_group": 34, "sparkoper": [34, 61], "api_vers": [34, 61], "basesensoroper": 34, "4": [34, 59, 60, 61], "where": [34, 39, 52, 53, 54, 55, 62], "resid": [34, 56], "determin": [34, 43, 59], "failure_st": 34, "unknown": [34, 58], "success_st": 34, "poke": 34, "render_k8s_pod_yaml": 35, "get_rendered_k8s_spec": 35, "db": [35, 52, 54, 59], "kubernetesjobtrigg": 37, "job_namespac": [37, 48, 61], "basetrigg": [37, 39], "kubernetescreatejobtrigg": 37, "classpath": [37, 39], "yield": [37, 39, 52, 54], "triggerev": [37, 39, 52, 54], "containerst": 39, "concept": [39, 43, 61], "workload": [39, 43, 59], "lifecycl": [39, 43, 61], "phase": [39, 43, 52], "undefin": [39, 52, 54], "kubernetespodtrigg": [39, 52, 54], "pod_namespac": 39, "trigger_start_tim": 39, "startup_check_interv": [39, 43], "should_delete_pod": 39, "kick": 39, "pendulum": [39, 43, 52, 54, 59], "kubernetescreatepodtrigg": 39, "define_container_st": 39, "should_wait": 39, "pod_phas": 39, "container_st": 39, "default_deletion_bodi": 40, "delete_from_dict": 40, "k8s_client": 40, "verbos": [40, 53], "delete_from_yaml": 40, "yaml_object": 40, "failtodeleteerror": 40, "api_except": 40, "__str__": 40, "podlaunchfailedexcept": 43, "should_retry_start_pod": 43, "podphas": [43, 52], "terminal_st": 43, "protocol": [43, 52, 54], "reli": [43, 52, 54], "upon": [43, 52, 54, 55], "subclass": [43, 52, 61], "mai": [43, 52, 54, 59, 61], "document": [43, 52, 53, 54, 55, 61], "kpo": [43, 52, 54, 61], "get_container_statu": 43, "container_is_run": 43, "examin": 43, "container_is_complet": 43, "container_is_succeed": 43, "container_is_termin": 43, "get_container_termination_messag": 43, "podlaunchtimeoutexcept": 43, "podnotfoundexcept": 43, "podloggingstatu": [43, 52, 54], "last": 43, "fetch_container_log": 43, "create_pod": [43, 52], "follow_container_log": [43, 52], "await_container_complet": [43, 52, 54], "await_pod_complet": [43, 52], "istio_en": 43, "get_container_nam": 43, "await_xcom_sidecar_container_start": 43, "extract_xcom_json": 43, "extract_xcom_kil": 43, "onfinishact": [43, 52, 54], "sidecar_container_imag": 44, "sidecar_container_resourc": 44, "exampl": [45, 46, 48, 49, 50, 52, 54, 55, 56, 58], "secret_fil": [45, 46, 61], "secret_env": [45, 46, 61], "secret_all_kei": [45, 46, 61], "init_container_volume_mount": [45, 46, 61], "init_environ": [45, 46, 61], "env_id": [45, 46, 48, 49, 50], "example_kubernetes_oper": 45, "k": [45, 46, 61], "test_run": [45, 46, 47, 48, 49, 50], "example_kubernetes_operator_async": 46, "execute_in_k8s_pod": 47, "example_kubernetes_job_oper": 48, "pi": [48, 50], "k8s_job": [48, 61], "In": [49, 50, 52, 56, 59, 61], "sequenti": [49, 50], "pvc": 49, "pvc_name": 49, "toto": 49, "pvc_conf": 49, "example_kubernetes_resource_oper": 49, "t1": 49, "instal": [50, 52, 54, 59, 60, 62], "spark_pi": 50, "pi_example_path": 50, "example_kubernet": [51, 54, 61], "example_kubernetes_async": [51, 61], "example_kubernetes_decor": 51, "example_kubernetes_job": [51, 61], "example_kubernetes_resourc": 51, "example_spark_kubernet": 51, "apach": [52, 55, 58, 59, 60, 61], "airflow": [52, 53, 55, 56, 58, 59, 60, 61, 62], "provid": [52, 53, 55, 58, 59, 60, 61, 62], "cncf": [52, 55, 58, 59, 60, 61], "kubernet": [52, 55, 58, 60], "38247": [52, 54], "38081": [52, 54], "gkecreatecustomresourceoper": [52, 54], "gkedeletecustomresourceoper": [52, 54], "37616": [52, 54], "38251": [52, 54], "38146": [52, 54], "38458": [52, 54], "38454": [52, 54], "38075": [52, 54], "37998": [52, 54], "sigint": [52, 54], "signal": [52, 54], "37905": [52, 54], "38106": [52, 54], "alloc": [52, 54], "38223": [52, 54], "38035": [52, 54], "reduc": [52, 54], "irrelev": [52, 54], "37944": [52, 54], "gkelistjobsoper": [52, 54], "gkedescribejoboper": [52, 54], "37598": [52, 54], "usag": [52, 53, 54], "38638": [52, 54], "deletekubernetesjoboper": [52, 54], "gkedeletejoboper": [52, 54], "37793": [52, 54], "gke": [52, 54], "38404": [52, 54], "immedi": [52, 54], "fatal": [52, 54, 55], "37670": [52, 54], "creation": [52, 54, 55], "37671": [52, 54], "recommend": [52, 54, 55, 58, 61], "37792": [52, 54], "migrat": [52, 54], "respect": [52, 54, 59], "37728": [52, 54], "exceed": [52, 55], "quota": [52, 55], "introduc": [52, 54], "task_publish_max_retri": 52, "flag": [52, 54, 55], "behavior": [52, 54], "unlimit": [52, 55], "posit": [52, 54, 59], "integ": [52, 55], "forev": [52, 54], "36882": [52, 54], "37279": [52, 54], "36847": [52, 54], "occasion": [52, 54], "attr": [52, 54], "37318": [52, 54], "hang": [52, 54, 55], "37300": [52, 54], "37271": [52, 54], "assign": [52, 54, 61], "__init__": [52, 54], "37010": [52, 54], "maintain": [52, 54], "37454": [52, 54], "37514": [52, 54], "keyerror": [52, 54], "soon": [52, 54], "37508": [52, 54], "feat": [52, 54], "switch": [52, 54], "class": [52, 54, 55, 57, 61], "36876": [52, 54], "bump": [52, 54], "37040": [52, 54], "gkestartkueueinsideclusteroper": [52, 54], "37072": [52, 54], "apiexcept": [52, 54], "correctli": [52, 54, 59], "37405": [52, 54], "22253": [52, 54], "36922": [52, 54], "35714": [52, 54], "36749": [52, 54], "stacklevel": [52, 54], "36831": [52, 54], "increas": [52, 54, 55], "tenac": [52, 54], "36955": [52, 54], "36888": [52, 54], "0rc1": [52, 54], "37001": [52, 54], "36752": [52, 54], "word": [52, 54], "docstr": [52, 54], "36547": [52, 54], "36281": [52, 54], "36397": [52, 54], "remind": [52, 54], "stub": [52, 54], "36434": [52, 54], "36355": [52, 54], "36433": [52, 54], "get_python_sourc": [52, 54], "min": [52, 53, 54], "36426": [52, 54], "duplic": [52, 54], "import": [52, 54, 58, 59, 61], "helper": [52, 54, 59], "36427": [52, 54], "_request_timeout": [52, 54], "36297": [52, 54], "33174": [52, 54], "stack": [52, 54], "trace": [52, 54], "35716": [52, 54], "equal": [52, 54, 61], "host_name_max": [52, 54], "36332": [52, 54], "move": [52, 54, 55], "36290": [52, 54], "slot": [52, 54], "leak": [52, 54], "36240": [52, 54], "signatur": [52, 54, 58], "36086": [52, 54], "optim": [52, 54, 61], "36092": [52, 54], "avail": [52, 53, 54, 55, 58, 61], "explain": 52, "36048": [52, 54], "stop": [52, 54], "taskinstancest": [52, 54], "35891": [52, 54], "35848": [52, 54], "minimum": [52, 53, 54, 57], "36017": [52, 54], "35641": [52, 54], "35600": [52, 54], "revert": [52, 54], "35422": [52, 54], "35822": [52, 54], "35185": [52, 54], "reappli": [52, 54], "35686": [52, 54], "inconsequenti": [52, 54], "bit": [52, 54], "35416": [52, 54], "observ": [52, 54], "improv": [52, 54], "35579": [52, 54], "verificationi": [52, 54], "35424": [52, 54], "34231": [52, 54], "before_log": [52, 54], "traceback": [52, 54], "35423": [52, 54], "tenanc": [52, 54], "inner": [52, 54], "func": [52, 54], "consume_log": [52, 54], "35504": [52, 54], "multi": [52, 54], "reconcili": [52, 54], "35450": [52, 54], "durat": [52, 54], "34985": [52, 54], "constant": [52, 54], "sentinel": [52, 54], "35451": [52, 54], "kubernetesoper": [52, 54, 61], "sub_path": [52, 54, 61], "35129": [52, 54], "hostalias": [52, 54], "35063": [52, 54], "35162": [52, 54], "35079": [52, 54], "multilin": [52, 54], "34412": [52, 54], "34579": [52, 54], "34500": [52, 54], "podlogsconsum": [52, 54], "34127": [52, 54], "34728": [52, 54], "level": [52, 54, 61], "34530": [52, 54], "34511": [52, 54], "34153": [52, 54], "34346": [52, 54], "34209": [52, 54], "textwrap": [52, 54], "34220": [52, 54], "soft_fail": [52, 54], "34167": [52, 54], "cached_properti": [52, 54], "34106": [52, 54], "34130": [52, 54], "combin": [52, 54], "33987": [52, 54], "useless": [52, 54], "join": [52, 54, 59], "33968": [52, 54], "unneed": [52, 54], "jump": [52, 54], "33833": [52, 54], "loop": [52, 54, 55], "33984": [52, 54], "outsid": [52, 54], "33977": [52, 54], "33933": [52, 54], "33939": [52, 54], "34110": [52, 54], "curl": [52, 54, 58], "quitquitquit": [52, 54], "oth": [52, 54], "33306": [52, 54], "33379": [52, 54], "33604": [52, 54], "33500": [52, 54], "33652": [52, 54], "rather": [52, 54], "last_stat": [52, 54], "decid": [52, 54, 62], "33702": [52, 54], "33779": [52, 54], "33378": [52, 54], "scc": [52, 54], "33381": [52, 54], "33629": [52, 54], "sort": [52, 54], "33675": [52, 54], "sqlalchemi": [52, 54], "queri": [52, 54], "style": [52, 54], "32883": [52, 54], "itertool": [52, 54], "33479": [52, 54], "len": [52, 54], "33569": [52, 54], "utc": [52, 54, 59], "33450": [52, 54], "33794": [52, 54], "33761": [52, 54], "probvid": [52, 54], "33781": [52, 54], "re2": [52, 54, 57], "celeri": [52, 54, 59], "33237": [52, 54], "kubernetespodoperatpor": [52, 54], "33228": [52, 54], "33230": [52, 54], "32627": [52, 54], "33127": [52, 54], "32858": [52, 54], "sub": [52, 54], "33090": [52, 54], "33057": [52, 54], "33081": [52, 54], "packag": [52, 55, 59, 60], "32767": [52, 54], "aip": [52, 54], "51": [52, 54], "29055": [52, 54], "32885": [52, 54], "sparkk8sop": [52, 54], "old": [52, 54], "32768": [52, 54], "info": [52, 54], "32536": [52, 54], "32931": [52, 54], "kubernetesoperatorpod": [52, 54], "31663": [52, 54], "32467": [52, 54], "30718": [52, 54], "32113": [52, 54], "strategi": [52, 54], "31348": [52, 54], "compatib": [52, 54], "31798": [52, 54], "31712": [52, 54], "drop": [52, 54, 58], "kubernetesresourceoper": [52, 54], "29930": [52, 54], "31985": [52, 54], "31595": [52, 54], "statement": [52, 54], "31703": [52, 54], "fargat": [52, 54], "aw": [52, 54, 61], "system": [52, 54, 59, 61], "31622": [52, 54], "30963": [52, 54], "31402": [52, 54], "behav": 52, "though": 52, "easier": 52, "mitig": 52, "conn": [52, 54], "31187": [52, 54], "31298": [52, 54], "pickl": [52, 54], "31110": [52, 54], "30917": [52, 54], "31228": [52, 54], "30992": [52, 54], "29498": [52, 54], "30769": [52, 54], "29000": [52, 54], "28848": [52, 54], "28125": [52, 54], "enhanc": [52, 54], "spark_k8s_oper": [52, 54], "29977": [52, 54], "29052": [52, 54], "28336": [52, 54], "align": [52, 54], "21": [52, 54], "29905": [52, 54], "boilerpl": [52, 54], "taskflow": [52, 54], "30118": [52, 54], "30216": [52, 54], "_render_nested_template_field": [52, 54], "29760": [52, 54], "28942": [52, 54], "29017": [52, 54], "28808": [52, 54], "29279": [52, 54], "incorrect": [52, 54], "28771": [52, 54], "flink": [52, 54], "28512": [52, 54], "relat": [52, 54, 61], "nest": [52, 54], "27719": [52, 54], "longer": [52, 54, 59], "27736": [52, 54], "exec": [52, 54], "28546": [52, 54], "27845": [52, 54], "under": [52, 54], "28237": [52, 54], "outdat": [52, 54], "28507": [52, 54], "restructur": [52, 54], "27235": [52, 54], "Such": 52, "consider": 52, "now": [52, 54], "backcompat": [52, 54], "librari": [52, 54], "27518": [52, 54], "27515": [52, 54], "unus": [52, 54], "27490": [52, 54], "27197": [52, 54], "26849": [52, 54], "27196": [52, 54], "econom": [52, 54], "27517": [52, 54], "suppli": [52, 61], "infer": 52, "backend": [52, 59], "necessari": [52, 55], "prefix": [52, 54], "extra__kubernetes__": [52, 54], "without": [52, 53, 54, 55], "27021": [52, 54], "27457": [52, 54], "26560": [52, 54], "26766": [52, 54], "convers": [52, 54], "27524": [52, 54], "27120": [52, 54], "27116": [52, 54], "27433": [52, 54], "absenc": [52, 54], "25787": [52, 54], "26999": [52, 54], "27516": [52, 54], "27202": [52, 54], "26848": [52, 54], "25530": [52, 54], "25663": [52, 54], "pretti": [52, 54], "25850": [52, 54], "calcul": [52, 54], "26377": [52, 54], "25055": [52, 54], "hint": [52, 54], "paramspec": [52, 54], "25173": [52, 54], "problem": [52, 54], "24993": [52, 54], "airflow_kpo_in_clust": [52, 54], "24658": [52, 54], "found": [52, 54, 62], "22092": [52, 54], "23883": [52, 54], "24474": [52, 54], "functool": [52, 54], "24582": [52, 54], "kub": [52, 54], "op": [52, 54], "k8s_resourc": [52, 54], "24673": [52, 54], "offici": [52, 58, 59], "oppos": 52, "prior": 52, "major": [52, 62], "20578": [52, 54], "22086": [52, 54], "23955": [52, 54], "24054": [52, 54], "remot": [52, 54, 59], "23676": [52, 54], "root": [52, 54, 61], "logger": [52, 54], "_suppress": [52, 54], "23835": [52, 54], "22441": [52, 54], "24132": [52, 54], "f": [52, 54, 59], "23597": [52, 54], "20966": [52, 54], "23301": [52, 54], "content": [52, 54], "defect": [52, 54], "23490": [52, 54], "clarifi": [52, 54], "23377": [52, 54], "22871": [52, 54], "inclust": [52, 54], "23126": [52, 54], "22734": [52, 54], "21092": [52, 54], "dup": [52, 54], "22845": [52, 54], "23371": [52, 54], "hyphen": [52, 54], "22982": [52, 54], "mypi": [52, 54], "main": [52, 54, 58, 62], "22884": [52, 54], "upgrad": [52, 54, 59, 62], "incompat": 52, "newer": 52, "22595": [52, 54], "approach": [52, 54], "bound": [52, 54], "22573": [52, 54], "22412": [52, 54], "22566": [52, 54], "unsupport": 52, "mistakenli": 52, "install_requir": 52, "22382": 52, "elasticsearch": [52, 54], "22385": [52, 54], "refreshconfigur": [52, 54], "workaround": [52, 54], "token": [52, 54], "refresh": [52, 54], "20759": [52, 54], "trove": 52, "classifi": [52, 54], "pypi": [52, 54, 61, 62], "framework": 52, "21916": [52, 54], "execution_d": [52, 53], "21960": [52, 54], "wrong": [52, 54], "21898": [52, 54], "21826": [52, 54], "20031": [52, 54], "18797": [52, 54], "20575": [52, 54], "19572": [52, 54], "pod_mutation_hook": [52, 54], "20596": [52, 54], "20576": [52, 54], "mean": [52, 61], "indefinit": [52, 54, 55], "With": [52, 59, 61], "mani": [52, 59, 61], "reflect": 52, "structur": [52, 54, 61], "addition": [52, 59], "did": 52, "directli": [52, 59, 61], "worri": [52, 58], "howev": [52, 59], "One": [52, 59], "princip": 52, "goal": 52, "clearli": 52, "encapsul": 52, "top": [52, 57, 58], "tri": [52, 56], "three": 52, "compon": [52, 59], "forward": 52, "harvest": 52, "await": 52, "extract": 52, "anew": 52, "handle_pod_overlap": 52, "create_new_pod_for_oper": 52, "unsuccessfulli": 52, "attempt": 52, "create_pod_launch": 52, "orchestr": [52, 61], "create_pod_request_obj": 52, "_get_ti_pod_label": 52, "inclus": [52, 54], "possibli": 52, "filter": [52, 54], "later": 52, "_get_pod_identifying_label_str": 52, "_build_find_pod_label_selector": 52, "_try_numbers_match": 52, "formerli": 52, "split": 52, "_task_statu": 52, "These": 52, "due": [52, 54, 55], "deal": [52, 59], "untransform": 52, "_extract_xcom": 52, "pod_launch": [52, 54], "lower": 52, "left": [52, 58, 59], "accumul": 52, "practic": 52, "seem": 52, "common": [52, 54], "temporari": [52, 58], "basi": [52, 55, 59], "purpos": 52, "therefor": 52, "sensibl": 52, "19695": [52, 54], "20573": [52, 54], "20574": [52, 54], "deprecationwarn": [52, 54], "19726": [52, 54], "19718": [52, 54], "decoupl": [52, 54], "19398": [52, 54], "container_status": [52, 54], "19713": [52, 54], "coalesc": [52, 54], "19694": [52, 54], "correct": [52, 54, 58, 61], "19459": [52, 54], "18928": [52, 54], "17953": [52, 54], "18070": [52, 54], "descript": [52, 54], "fit": [52, 54], "18377": [52, 54], "17649": [52, 54], "17760": [52, 54], "lazili": [52, 54], "individu": [52, 54, 61], "17682": [52, 54], "16945": [52, 54], "bugfix": [52, 54, 62], "caus": [52, 54], "16930": [52, 54], "auto": [52, 54], "apply_default": [52, 54], "15667": [52, 54], "least": 52, "automat": [52, 54, 59], "manual": 52, "15942": [52, 54], "save": [52, 54], "15755": [52, 54], "15787": [52, 54], "16095": [52, 54], "15638": [52, 54], "unsuccess": [52, 54], "final_st": [52, 54], "15490": [52, 54], "15373": [52, 54], "proper": [52, 54], "15507": [52, 54], "15388": [52, 54], "15492": [52, 54], "15165": [52, 54], "abil": [52, 54, 59, 61], "14898": [52, 54], "libyaml": [52, 54], "c": [52, 54, 61], "14577": [52, 54], "pod_templ": [52, 59], "14186": [52, 54], "actual": 52, "14083": [52, 54], "readm": [52, 54], "13289": [52, 54], "below": [53, 55, 57, 58, 59, 61], "7": [53, 55, 59, 60], "h": 53, "group_or_command": 53, "choic": 53, "tool": [53, 54], "help": [53, 59], "evict": [53, 61], "minut": 53, "min_pending_minut": 53, "v": 53, "measur": 53, "m": 53, "o": [53, 58, 59], "output_path": 53, "subdir": 53, "cwd": 53, "locat": [53, 56, 61], "directori": [53, 58], "airflow_hom": [53, 59], "commit": 54, "high": 54, "changelog": 54, "2024": 54, "04": [54, 61], "15": 54, "subject": 54, "43919c2fa6": 54, "5fa80b6aea": 54, "prepar": [54, 62], "1st": 54, "wave": 54, "rc1": 54, "april": 54, "38863": 54, "78f84b9147": 54, "09": 54, "fix": [54, 59, 62], "try002": 54, "38799": 54, "a19a9cb523": 54, "05": 54, "ab5aabe50b": 54, "02": 54, "ec6091d498": 54, "03": 54, "31": 54, "afb686c95": 54, "26": 54, "a3f7ddd465": 54, "32ed83bd0": 54, "refactor": 54, "fc868f4be2": 54, "22": 54, "1a9b71a129": 54, "29ac05f496": 54, "18": 54, "b5b972a106": 54, "yank": 54, "38262": 54, "d4350a6b": 54, "0a74928894": 54, "ruff": 54, "38240": 54, "f3982aa2a4": 54, "c32d41d94d": 54, "1d3010c4ab": 54, "8f773a62c1": 54, "08": 54, "a7b7928a2a": 54, "07": 54, "8e6f78a735": 54, "06": 54, "ca72f0fd89": 54, "83316b8158": 54, "march": 54, "37876": 54, "30f7b2abe6": 54, "broad": 54, "noqa": 54, "37862": 54, "d470674912": 54, "01": 54, "77341ef6a1": 54, "29": [54, 57], "cd33c2a6a7": 54, "27": 54, "c6ba13adf2": 54, "19": 54, "fa234e0d22": 54, "rc3": 54, "februari": 54, "37521": 54, "6412b06a7b": 54, "d50a25bd35": 54, "17": 54, "75182363a2": 54, "rc2": 54, "37471": 54, "5a0be392e6": 54, "16": [54, 61], "comment": 54, "37488": 54, "c84efe77a5": 54, "32ba99b6c2": 54, "0be6430938": 54, "37363": 54, "37446": 54, "df132b2dd6": 54, "0640e6d595": 54, "34c06c6922": 54, "bfb054e9e8": 54, "37326": 54, "053485ba56": 54, "f689c3f606": 54, "d401": 54, "37301": 54, "6246eec96f": 54, "e99487946a": 54, "9a529a8d43": 54, "f691adf710": 54, "7932958488": 54, "dec2662190": 54, "c36c4db3f7": 54, "cead3da4a6": 54, "2nd": 54, "round": 54, "jan": 54, "37019": 54, "dd627d7f46": 54, "d78a114aa0": 54, "23": [54, 57], "2b4da0101f": 54, "januari": 54, "36945": 54, "43d192543e": 54, "20": 54, "6dc53524a5": 54, "d3b4a91135": 54, "6ff96af480": 54, "142f08abb5": 54, "aa25affec6": 54, "2ffa6e4c4c": 54, "19ebcac239": 54, "36640": 54, "2f15c95a28": 54, "6937ae7647": 54, "2023": 54, "speed": 54, "autocomplet": 54, "breez": 54, "36499": 54, "28": [54, 57], "9b5d6bfe27": 54, "3rd": 54, "deember": 54, "36464": 54, "2bd60771a8": 54, "a7700c1567": 54, "ee219e658d": 54, "af9328e6ff": 54, "3f60482974": 54, "24": 54, "63544e184d": 54, "b15d5578da": 54, "decemb": 54, "36380": 54, "f5883d6e7b": 54, "36373": 54, "33ee0b98b2": 54, "381922f7c0": 54, "49108e15eb": 54, "5ab43d5541": 54, "f81dfd731f": 54, "a398d9d4fa": 54, "cd476acd8f": 54, "b9c574c61a": 54, "999b70178a": 54, "36112": 54, "d0918d77ee": 54, "1264316fe7": 54, "drive": 54, "36062": 54, "de71a62848": 54, "f5259376b8": 54, "change_st": 54, "35900": 54, "623f989329": 54, "e57232ff8f": 54, "0b23d5601c": 54, "novemb": 54, "35836": 54, "0e157b38a3": 54, "ca97feed18": 54, "8dc1b23116": 54, "99534e47f3": 54, "reproduc": 54, "35693": 54, "99df205f42": 54, "6f51e502df": 54, "486ccba4cf": 54, "31450bbe3c": 54, "cd296d2068": 54, "4b1e494f47": 54, "bandit": 54, "pre": 54, "34247": 54, "1b059c57d6": 54, "35537": 54, "d6c79ce340": 54, "68b3b7b468": 54, "be2c3b9d9": 54, "c67a2b0413": 54, "a61da3cc87": 54, "2023a76037": 54, "2b0bfea837": 54, "3724a029da": 54, "63cc915cd3": 54, "black": 54, "formatt": 54, "35287": 54, "d1c58d86de": 54, "octob": 54, "35233": 54, "3592ff4046": 54, "35187": 54, "85f0ef35b8": 54, "d4002261b5": 54, "4767f48a3b": 54, "4c8c85ccc2": 54, "dd7ba3cae1": 54, "292": 54, "35053": 54, "b75f9e8806": 54, "35033": 54, "f23170c9dd": 54, "thru": 54, "34934": 54, "e9987d5059": 54, "34916": 54, "0c8e30e43b": 54, "4234d8db7e": 54, "cbb04e5133": 54, "bd512007e5": 54, "7ebf4220c9": 54, "34320": 54, "fb92ff8486": 54, "a169cf2c25": 54, "rst": 54, "34625": 54, "08729eddbd": 54, "659d94f0ae": 54, "8ecd576de1": 54, "shorter": 54, "34347": 54, "7574e16e75": 54, "sep": [54, 58], "34360": 54, "de92a81f00": 54, "b435b8edef": 54, "b5057e0e1f": 54, "c5016f754d": 54, "21990ed894": 54, "34201": 54, "6e1de4f9b9": 54, "1005501365": 54, "7731255975": 54, "5e6e107f73": 54, "fa5e54c4c5": 54, "47bd5dd0e1": 54, "875387afa5": 54, "ff7dcf4e82": 54, "1b122c1503": 54, "55976af32": 54, "concatin": 54, "f66df7f6bc": 54, "23174ef1bb": 54, "aug": 54, "33868": 54, "cede385e93": 54, "452a978337": 54, "42bc8fcb6b": 54, "b11525702c": 54, "c077d19060": 54, "33730": 54, "c477031039": 54, "85acbb4ae9": 54, "6130993d78": 54, "2dbb963324": 54, "75ce4d1923": 54, "4bdf908041": 54, "0ca5f700ab": 54, "33641": 54, "a54c2424df": 54, "typo": 54, "doubl": 54, "33623": 54, "7141c42cc3": 54, "4c4981d1ad": 54, "95a930bc0a": 54, "1cdd82391e": 54, "e991f60a79": 54, "bfe08a79db": 54, "46ffc25995": 54, "38aada7b8b": 54, "7e79997594": 54, "d205": 54, "33303": 54, "b5a4d36383": 54, "33291": 54, "1f6257110d": 54, "0b528e2b2": 54, "056f1670fe": 54, "9556d6d5f6": 54, "60677b0ba3": 54, "33128": 54, "f4542a30b0": 54, "4fbbdbc9b1": 54, "33092": 54, "33125": 54, "164526d4c7": 54, "d31c77510c": 54, "900ad8c190": 54, "879fd34e97": 54, "f83d63ea54": 54, "d06b7af69a": 54, "juli": 54, "32875": 54, "bcc7856b80": 54, "f31af91dbd": 54, "fcbbf47864": 54, "e93460383f": 54, "fcc6f284c7": 54, "e01323635a": 54, "e7f59a913": 54, "32566": 54, "b3ce116192": 54, "c99c03135c": 54, "straggler": 54, "32447": 54, "9a0f41ba53": 54, "225e3041d2": 54, "32381": 54, "3878fe6fab": 54, "spuriou": 54, "header": 54, "32373": 54, "cb4927a018": 54, "32298": 54, "f8593503cb": 54, "df4c8837d0": 54, "dd937e51f": 54, "8f5de83ee6": 54, "8c37b74a20": 54, "32226": 54, "6693bdd72d": 54, "09d4718d3a": 54, "32125": 54, "79bcc2e668": 54, "june": 54, "32001": 54, "8b146152d6": 54, "32015": 54, "66299338eb": 54, "07ea574f": 54, "d400": 54, "pydocstyl": 54, "31742": 54, "d8086a3db5": 54, "def4b53765": 54, "86b5ba2802": 54, "0fa8c44527": 54, "dc5bf3fd02": 54, "discover": 54, "31576": 54, "a59076eae": 54, "31427": 54, "9fa75aaf7a": 54, "45548b9451": 54, "31416": 54, "a1f5a5425": 54, "54f1fb0574": 54, "31375": 54, "abea189022": 54, "31393": 54, "f5aed58d9f": 54, "circular": 54, "31379": 54, "d9ff55cf6d": 54, "31252": 54, "caeca2d143": 54, "774a5a9038": 54, "e7cb9ca2c1": 54, "31191": 54, "8eab2e54e": 54, "c3c90eaa94": 54, "dcf3d39a15": 54, "0a30706aa7": 54, "airflowproviderdeprecationwarn": 54, "30975": 54, "eef5bc7f16": 54, "autom": 54, "30994": 54, "a7eb32a5b2": 54, "9409446097": 54, "30822": 54, "b5296b7436": 54, "c585ad51c5": 54, "262": 54, "30809": 54, "e46ce78b66": 54, "adhoc": 54, "30787": 54, "ebe2f2f626": 54, "skip_exit_cod": 54, "30788": 54, "afdc95435b": 54, "99a3bf2318": 54, "30733": 54, "f511653e5a": 54, "874ea9588": 54, "hoc": 54, "30545": 54, "85b9135722": 54, "dc4dd9178c": 54, "d23a3bbed8": 54, "mechan": [54, 55], "30422": 54, "55dbf1ff1f": 54, "30378": 54, "df49ad179b": 54, "b8ab594130": 54, "9a4f674852": 54, "c3867781e0": 54, "29950": 54, "1e81a98cc6": 54, "971039454a": 54, "6d2face107": 54, "fcd3c0149f": 54, "29878": 54, "1e536eb43d": 54, "dba390e323": 54, "augment": 54, "languag": [54, 61], "ci": 54, "29549": 54, "470fdaea27": 54, "midmonth": 54, "29589": 54, "9a5c3e0ac0": 54, "ce6ae2457": 54, "feb": 54, "29379": 54, "d26dc22391": 54, "246d778e6b": 54, "70b84b51a5": 54, "911b708ffd": 54, "mid": 54, "month": 54, "28929": 54, "ce858a5d71": 54, "faster": 54, "28893": 54, "ce677862b": 54, "5246c009c5": 54, "28651": 54, "c22fc000b6": 54, "2022": 54, "681835a67c": 54, "38e40c6dc4": 54, "401fc57e8b": 54, "bdc3d2e647": 54, "d93240696b": 54, "33c445d92f": 54, "ebd7b67dcb": 54, "25bdbc8e67": 54, "27937": 54, "2e20e9f7eb": 54, "relas": 54, "27774": 54, "12c3c39d1a": 54, "27613": 54, "52593b061c": 54, "47a2b9ee7f": 54, "aefadb8c5b": 54, "2d2f0daad6": 54, "eee3df4570": 54, "8c15b0a6d1": 54, "20ecefa416": 54, "701239abc3": 54, "9337aa92c0": 54, "3aadc44a13": 54, "0c26ec07b": 54, "4797a0322": 54, "9ab1a6a3e7": 54, "26872": 54, "734995ff26": 54, "unset": 54, "78b8ea2f22": 54, "2a34dc9e84": 54, "27205": 54, "14a45872e2": 54, "3ecb8dd025": 54, "c9e57687b0": 54, "2752f2add1": 54, "5c97e5be48": 54, "53d68049d9": 54, "f8db64c35c": 54, "septemb": 54, "26731": 54, "1a07cbe423": 54, "26588": 54, "e60a459d56": 54, "06acf40a43": 54, "pep": 54, "563": 54, "postpon": 54, "evalu": 54, "26289": 54, "4b26c8c541": 54, "0eb0b543a9": 54, "db5543ef60": 54, "ccdd73ec50": 54, "e5ac6c7cfb": 54, "august": 54, "25618": 54, "c8af0592c0": 54, "f05a06537b": 54, "d2459a241b": 54, "25030": 54, "ef79a0d1c4": 54, "assert": 54, "stuff": 54, "24937": 54, "e2fd41f7b1": 54, "xcom_push": 54, "24823": 54, "9d307102b4": 54, "minor": [54, 62], "24719": 54, "0de31bd73a": 54, "folder": [54, 58, 59], "24672": 54, "45b11d4ed1": 54, "24720": 54, "510a6bab45": 54, "24702": 54, "5326da4b83": 54, "45f4290712": 54, "renam": 54, "9c59831ee7": 54, "78ac48872b": 54, "dba3e4ec51": 54, "dcdcf3a2b8": 54, "24307": 54, "717a7588bc": 54, "24292": 54, "b1ad017ce": 54, "d202": 54, "24221": 54, "aeabe994b3": 54, "24231": 54, "98b4e48fbc": 54, "42abbf0d61": 54, "027b707d21": 54, "explanatori": 54, "contributor": 54, "24229": 54, "7ad4e67c1a": 54, "60eb9e106f": 54, "e240132934": 54, "6bbe015905": 54, "ec6761a5c0": 54, "064c41afda": 54, "75c60923e0": 54, "23631": 54, "2eeb120bf4": 54, "randomli": 54, "consumpt": [54, 59], "23497": 54, "23618": 54, "23656": 54, "ee342b85b9": 54, "863b257642": 54, "faae9faae3": 54, "dbdcd0fd1d": 54, "a914ec22c1": 54, "23378": 54, "11bbe471cd": 54, "23374": 54, "8e3abe4180": 54, "8b6b0848a3": 54, "brees": 54, "verifi": [54, 55, 56], "23104": 54, "c7399c7190": 54, "70eede5dd6": 54, "c3d883a971": 54, "d81703c577": 54, "3c5bc73579": 54, "6933022e94": 54, "04082ac091": 54, "56ab82ed7a": 54, "22819": 54, "67e2723b73": 54, "6db30f3207": 54, "0d64d66cea": 54, "0a99be7411": 54, "d7dbfb7e26": 54, "22383": 54, "0f977daa3c": 54, "7bd165fbe2": 54, "16adc035b1": 54, "22226": 54, "f5b96315fe": 54, "22056": 54, "8d8d072289": 54, "kubepodoper": 54, "exeuction_d": 54, "6c37e47cf6": 54, "351fa53432": 54, "a159ae828f": 54, "0a3ff43d41": 54, "21398": 54, "d94fa37830": 54, "delai": 54, "21439": 54, "6c3a67d4fc": 54, "2021": [54, 58, 59], "21257": 54, "4a73d8f3d1": 54, "cb73053211": 54, "21074": 54, "602abe8394": 54, "sphinx": 54, "autoapi": 54, "typehint": 54, "20951": 54, "428bd5f228": 54, "promin": 54, "20753": 54, "5569b868a9": 54, "tableau": 54, "20654": 54, "da9210e89c": 54, "20765": 54, "7222f68d37": 54, "f77417eb0d": 54, "20614": 54, "97496ba2b4": 54, "20523": 54, "83f8e178ba": 54, "even": [54, 61], "ext": 54, "20608": 54, "746ee587da": 54, "d56ff765e1": 54, "e63417553f": 54, "ca6c210b7d": 54, "e07e831946": 54, "d56e7b56bb": 54, "friendli": 54, "20571": 54, "a0821235fb": 54, "everywher": 54, "20565": 54, "f200bb1977": 54, "4b8a1201a": 54, "2fb5e1d0ec": 54, "declar": 54, "20226": 54, "f9eab1c185": 54, "853576d901": 54, "19882": 54, "fe682ec3d3": 54, "19759": 54, "0d60d1af41": 54, "1e57022953": 54, "f7410dfba2": 54, "bf5f452413": 54, "854b70b904": 54, "d9567eb106": 54, "19321": 54, "0a6850647": 54, "19057": 54, "1571f80546": 54, "misspel": 54, "18964": 54, "b2045d6d1d": 54, "c8b86e69e4": 54, "840ea3efb9": 54, "18613": 54, "ef037e7021": 54, "start_dat": [54, 59], "misc": 54, "18597": 54, "7808be7ffb": 54, "b8d06e812a": 54, "64d2f5488f": 54, "0a68588479": 54, "17890": 54, "42e13e1a5a": 54, "17900": 54, "bb5602c652": 54, "17798": 54, "be75dcd39c": 54, "meta": 54, "73d2b720e0": 54, "76ed2a49c6": 54, "97428efc41": 54, "mess": 54, "17380": 54, "b0b2591071": 54, "17256": 54, "997f7d0beb": 54, "17237": 54, "87f408b1e7": 54, "17116": 54, "d48b4e0caf": 54, "default_arg": 54, "16870": 54, "3939e84161": 54, "d02ded65ea": 54, "wrongli": 54, "escap": 54, "amazon": 54, "17020": 54, "b916b75079": 54, "17015": 54, "b2c66e45b7": 54, "9d6ae609b6": 54, "16624": 54, "866a601b76": 54, "pylint": 54, "toolchain": 54, "16682": 54, "bbc627a3da": 54, "16501": 54, "4c9735ff9b": 54, "kubernetespod": 54, "cbf8001d76": 54, "buggfix": 54, "16464": 54, "1fba5402bb": 54, "16405": 54, "4752fb3eb8": 54, "9c94b72d44": 54, "16294": 54, "2f16757e1a": 54, "bug": [54, 62], "476d0f6e3d": 54, "pyupgrad": 54, "v2": [54, 59], "15991": 54, "85b2ccb0c5": 54, "kubernetespodoperat": 54, "733bec9a04": 54, "37d549bde7": 54, "37681bca00": 54, "807ad32ce5": 54, "pip": [54, 57, 58, 59, 60], "15576": 54, "5b2fe0e740": 54, "popular": 54, "15393": 54, "53fc1a9679": 54, "d3cc67aa7a": 54, "be421a6b07": 54, "kubernetspodoper": 54, "44480d3673": 54, "b4770725a3": 54, "link": [54, 58], "15316": 54, "1806670383": 54, "409": 54, "15137": 54, "042be2e4e0": 54, "15236": 54, "6d7a70b88": 54, "00453dc4a2": 54, "68e4c4dcb0": 54, "backport": 54, "14886": 54, "e7bb17aeb8": 54, "built": [54, 59], "14606": 54, "7daebefd15": 54, "589d6dec92": 54, "14487": 54, "809b4f9b18": 54, "649335c043": 54, "14123": 54, "d4c4db8a18": 54, "10343ec29f": 54, "rc": 54, "14082": 54, "88bdcfa0df": 54, "14013": 54, "ac2f72c98d": 54, "13767": 54, "a9ac2b040b": 54, "flynt": 54, "13732": 54, "1b9e3d1c28": 54, "quick": 54, "13621": 54, "13835": 54, "94d3ed61d6": 54, "3fd5ef3555": 54, "logo": 54, "13717": 54, "295d66f914": 54, "2020": 54, "grammar": 54, "13380": 54, "7a560ab6d": 54, "6cf76d7ac0": 54, "13148": 54, "32971a1a2d": 54, "12955": 54, "b40dffa085": 54, "rema": 54, "12917": 54, "9b39f24780": 54, "per": [54, 55, 59], "12558": 54, "bd90136aaf": 54, "12681": 54, "2037303eef": 54, "discoveri": 54, "12466": 54, "de3b1e687b": 54, "12653": 54, "c02a3f59e4": 54, "properli": 54, "11199": 54, "c34ef853c8": 54, "12444": 54, "9e089ab895": 54, "12479": 54, "d32fe78c0d": 54, "12457": 54, "d84a52dc8f": 54, "broken": [54, 55], "12455": 54, "7c8b71d201": 54, "further": [54, 61], "12451": 54, "0080354502": 54, "0b2": 54, "12449": 54, "7ca0b6f121": 54, "markdownlint": 54, "md003": 54, "head": 54, "12427": 54, "12438": 54, "763b40d223": 54, "12432": 54, "bc4bb30588": 54, "12422": 54, "cab86d80d4": 54, "k8spodoper": 54, "12384": 54, "ae7cb4a1e2": 54, "12390": 54, "6889a333cf": 54, "12366": 54, "221f809c1b": 54, "12354": 54, "7825e8f590": 54, "12304": 54, "85a18e13d9": 54, "project": [54, 61], "page": [54, 55, 58], "cross": 54, "12212": 54, "59eb5de78c": 54, "0beta1": 54, "12206": 54, "3f59e75cdf": 54, "12171": 54, "b2a28d1590": 54, "dev": [54, 61], "12082": 54, "7825be50d8": 54, "12117": 54, "91a64db505": 54, "excepion": 54, "12091": 54, "4e8f9cc8d0": 54, "formmatt": 54, "9550": 54, "8c42cf1b00": 54, "11447": 54, "5a439e84eb": 54, "2a1": 54, "11855": 54, "872b1566a1": 54, "11826": 54, "53e6062105": 54, "enforc": 54, "strict": [54, 59, 62], "yamllint": 54, "11709": 54, "349b0811c3": 54, "d200": 54, "11688": 54, "eee4e30f2c": 54, "better": [54, 55], "k8sexec": 54, "k8spodop": 54, "11502": 54, "16e7129719": 54, "11487": 54, "8640fb6c10": 54, "11368": 54, "298052fcee": 54, "11008": 54, "49aad025b5": 54, "11369": 54, "b93b6c5be3": 54, "10796": 54, "0a0e1af800": 54, "markdown": 54, "toc": 54, "11249": 54, "ca4238eb4d": 54, "11242": 54, "5220e4c384": 54, "11238": 54, "a888198c27": 54, "11162": 54, "0161b5ea2b": 54, "coverag": 54, "11159": 54, "e3f96ce7a8": 54, "11138": 54, "f3e87c5030": 54, "11032": 54, "b61225a885": 54, "d204": 54, "11031": 54, "cba51d49e": 54, "k8sexecutor": 54, "10393": 54, "1294e15d44": 54, "10963": 54, "5d6d5a2f7d": 54, "10453": 54, "7edfac957b": 54, "10447": 54, "9549274d11": 54, "8b1": 54, "10818": 54, "90c1505686": 54, "grace_period_second": [54, 55], "10727": 54, "338b412c04": 54, "10666": 54, "596bc13379": 54, "10659": 54, "1e5aa4465c": 54, "10023": 54, "fdd9b6f65b": 54, "10543": 54, "2f2d8dbfaf": 54, "noinspect": 54, "intellij": 54, "10525": 54, "7c206a82a6": 54, "assig": 54, "10468": 54, "8cd2be9e16": 54, "10230": 54, "cdec301254": 54, "10205": 54, "24c8e4c2d6": 54, "constructor": 54, "10163": 54, "aeea71274d": 54, "10097": 54, "f1fd3e2c45": 54, "10056": 54, "03c4351744": 54, "10068": 54, "88c1603060": 54, "10049": 54, "7d24b088cd": 54, "example_dag": [54, 59], "9985": 54, "33f0cd2657": 54, "9784": 54, "c2db0dfeb1": 54, "9705": 54, "9906": 54, "719ae2bf62": 54, "9895": 54, "840799d559": 54, "9079": 54, "44d4ae809c": 54, "9686": 54, "8bd15ef634": 54, "helm": [54, 59], "chart": [54, 59], "9468": 54, "40bf8f28f9": 54, "lack": 54, "9290": 54, "1d36b0303b": 54, "8984": 54, "e742ef7c70": 54, "test_project_structur": 54, "8978": 54, "375d1ca229": 54, "candid": 54, "8898": 54, "12c5e5d8a": 54, "8891": 54, "8985df0bfc": 54, "6377": 54, "f3521fb0e3": 54, "regener": 54, "8886": 54, "92585ca4cb": 54, "8807": 54, "f82ad452b0": 54, "8829": 54, "1ccafc617c": 54, "7875": 54, "cd546b664f": 54, "super": 54, "7825": 54, "6c39a3bf97": 54, "6542": 54, "7163": 54, "42eef38217": 54, "6877": 54, "7506": 54, "3320e432a1": 54, "6817": 54, "lazi": 54, "face": 54, "untouch": 54, "7517": 54, "0ec2774120": 54, "5629": 54, "priorityclassnam": 54, "7395": 54, "9cbd7de6d1": 54, "6792": 54, "_oper": 54, "_hook": 54, "_sensor": 54, "7412": 54, "967930c0cb": 54, "5413": 54, "6230": 54, "96f834389e": 54, "6678": 54, "7292": 54, "97a429f9d0": 54, "6714": 54, "magic": 54, "utf": 54, "7338": 54, "cf141506a2": 54, "6708": 54, "7330": 54, "373c6aa4a2": 54, "6682": 54, "gcp": 54, "7295": 54, "83c037873f": 54, "6674": [54, 58], "accord": 54, "7287": 54, "059eda05f8": 54, "6610": 54, "softwar": [54, 58], "7231": 54, "embed": [55, 61], "urllib3": 55, "airflow__kubernetes_executor__api_client_retry_configur": 55, "total": 55, "backoff_factor": 55, "blank": [55, 59], "kubectl": [55, 61], "airflow__kubernetes_executor__cluster_context": 55, "configfil": 55, "airflow__kubernetes_executor__config_fil": 55, "keyword": 55, "delete_namespaced_pod": 55, "core_v1_api": 55, "v1deleteopt": 55, "41f11a09995efcd0142e25946adc7591431bfb2f": 55, "v1_delete_opt": 55, "l19": 55, "airflow__kubernetes_executor__delete_option_kwarg": 55, "airflow__kubernetes_executor__delete_worker_pod": 55, "investig": 55, "prevent": 55, "itself": [55, 59, 62], "ran": 55, "airflow__kubernetes_executor__delete_worker_pods_on_failur": 55, "tcp": [55, 56], "idl": 55, "cloud": 55, "balanc": 55, "firewal": 55, "airflow__kubernetes_executor__enable_tcp_keepal": 55, "give": 55, "intend": 55, "airflow__kubernetes_executor__in_clust": 55, "henc": 55, "raw": 55, "githubusercont": 55, "airflow__kubernetes_executor__kube_client_request_arg": 55, "traceabl": 55, "airflow__kubernetes_executor__logs_task_metadata": 55, "Will": 55, "role": 55, "airflow__kubernetes_executor__multi_namespace_mod": 55, "permiss": 55, "airflow__kubernetes_executor__multi_namespace_mode_namespace_list": 55, "airflow__kubernetes_executor__namespac": 55, "airflow__kubernetes_executor__pod_template_fil": 55, "ca": 55, "certif": [55, 56, 58], "server": [55, 58, 61], "airflow__kubernetes_executor__ssl_ca_cert": 55, "airflow__kubernetes_executor__task_publish_max_retri": 55, "respond": 55, "probe": 55, "retransmit": 55, "airflow__kubernetes_executor__tcp_keep_cnt": 55, "airflow__kubernetes_executor__tcp_keep_idl": 55, "airflow__kubernetes_executor__tcp_keep_intvl": 55, "airflow__kubernetes_executor__verify_ssl": 55, "airflow__kubernetes_executor__worker_container_repositori": 55, "tag": [55, 59], "airflow__kubernetes_executor__worker_container_tag": 55, "createcontainerconfigerror": 55, "errimagepul": 55, "createcontainererror": 55, "imageinspecterror": 55, "invalidimagenam": 55, "airflow__kubernetes_executor__worker_pod_pending_fatal_container_state_reason": 55, "highli": 55, "airflow__kubernetes_executor__worker_pods_creation_batch_s": 55, "often": 55, "60": 55, "airflow__kubernetes_executor__worker_pods_queued_check_interv": 55, "task_queued_timeout": 55, "task_queued_timeout_check_interv": 55, "airflow__local_kubernetes_executor__kubernetes_queu": 55, "There": [56, 58], "machin": 56, "insert": 56, "By": [56, 58, 59, 61], "aliv": 56, "alpin": [56, 61], "uri": 56, "airflow_conn_kubernetes_default": 56, "2f": 56, "2fconfig": 56, "And": [56, 59], "my": 56, "aiofil": 57, "asgiref": 57, "cryptographi": 57, "kubernetes_asyncio": [57, 61], "download": 58, "most": 58, "sdist": 58, "whl": 58, "checksum": 58, "foundat": 58, "asc": 58, "sha512": 58, "pgp": 58, "essenti": 58, "sha": 58, "gpg": 58, "relev": 58, "distribut": [58, 59], "mirror": [58, 61], "pgpk": 58, "ka": 58, "To": [58, 59, 61], "binari": 58, "pgpv": 58, "tar": 58, "gz": 58, "sat": 58, "11": 58, "12": 58, "49": 58, "54": 58, "bst": 58, "rsa": 58, "cde15c6e4d3a8ec4ecf4ba4b6674e08ad7de406f": 58, "issuer": 58, "kaxilnaik": 58, "org": 58, "good": [58, 61, 62], "kaxil": 58, "naik": 58, "aka": 58, "gmail": 58, "certifi": 58, "trust": 58, "owner": 58, "primari": [58, 61], "fingerprint": 58, "cde1": 58, "5c6e": 58, "4d3a": 58, "8ec4": 58, "ecf4": 58, "ba4b": 58, "e08a": 58, "d7de": 58, "406f": 58, "sign": 58, "why": 58, "know": 58, "sum": 58, "shasum": 58, "512": 58, "diff": 58, "bin": [58, 61], "bash": [58, 59, 61], "package_vers": 58, "package_nam": 58, "provider_download_dir": 58, "mktemp": 58, "d": [58, 61], "dep": 58, "dest": 58, "apache_airflow_providers_cncf_kubernet": 58, "py3": 58, "l": 58, "echo": [58, 59, 61], "la": 58, "instruct": [58, 62], "chapter": 58, "As": [59, 60, 61], "necessarili": 59, "sqlite": 59, "databas": 59, "report": 59, "five": 59, "shown": 59, "regular": 59, "architectur": 59, "free": 59, "assum": 59, "arrai": 59, "through": [59, 61], "guarante": 59, "across": 59, "mind": 59, "basic": [59, 61], "explicitli": [59, 61], "sql": 59, "apivers": [59, 61], "airflow__core__executor": 59, "hard": 59, "airflow__core__fernet_kei": 59, "valuefrom": [59, 61], "secretkeyref": [59, 61], "fernet": 59, "airflow__database__sql_alchemy_conn": 59, "airflow_conn_airflow_db": 59, "dummy_imag": 59, "imagepullpolici": [59, 61], "ifnotpres": 59, "mountpath": [59, 61], "opt": 59, "readonli": 59, "subpath": 59, "restartpolici": [59, 61], "never": [59, 61], "securitycontext": 59, "runasus": 59, "50000": 59, "fsgroup": 59, "serviceaccountnam": 59, "serviceaccount": [59, 61], "emptydir": 59, "persistentvolumeclaim": [59, 61], "claimnam": [59, 61], "git": 59, "dummi": 59, "initcontain": 59, "registri": 59, "v3": [59, 61], "git_sync_branch": 59, "stabl": 59, "git_sync_repo": 59, "git_sync_depth": 59, "git_sync_root": 59, "git_sync_dest": 59, "repo": 59, "git_sync_add_us": 59, "git_sync_one_tim": 59, "offer": 59, "fill": 59, "overwrit": 59, "example_kubernetes_executor": 59, "executor_config_volume_mount": 59, "foo": [59, 61], "host_path": 59, "v1hostpathvolumesourc": 59, "tmp": [59, 61], "def": [59, 61], "test_volume_mount": 59, "open": 59, "volume_mount_test": 59, "txt": 59, "w": 59, "write": [59, 61], "hello": [59, 61], "return_cod": 59, "cat": 59, "valueerror": 59, "volume_task": 59, "devic": 59, "executor_config_sidecar": 59, "share": 59, "dir": 59, "ubuntu": [59, 61], "cx": [59, 61], "empty_dir": 59, "v1emptydirvolumesourc": 59, "test_sharedvolume_mount": 59, "sidecar_task": 59, "recycl": 59, "both": 59, "lib": 59, "print_stuff": 59, "example_pod_template_fil": 59, "tz": 59, "catchup": 59, "example3": 59, "executor_config_templ": 59, "basic_templ": 59, "v1objectmeta": [59, 61], "task_with_templ": 59, "persist": 59, "webserv": 59, "lost": 59, "contrast": 59, "redi": 59, "histor": 59, "burstabl": 59, "scale": 59, "tend": 59, "latenc": 59, "On": 59, "hand": 59, "particularli": 59, "memori": [59, 61], "deploi": 59, "elaps": 59, "anoth": 59, "veri": 59, "uniform": 59, "celerykubernetesexecutor": 59, "simultan": [59, 60], "effect": [59, 61], "matter": [59, 61], "troubleshoot": 59, "moment": 59, "oom": 59, "discov": 59, "subscrib": 59, "everi": 59, "alert": 59, "recov": 59, "monoton": 59, "rise": 59, "off": 59, "independ": [59, 62], "lead": 59, "chosen": 60, "capabl": 60, "special": 61, "ekspodoper": 61, "elast": 61, "public": 61, "ultim": 61, "act": 61, "manifest": 61, "runtim": 61, "dry": 61, "debian": 61, "bar": 61, "dry_run_demo": 61, "overlap": 61, "great": 61, "consequ": 61, "safeti": 61, "almost": 61, "conveni": 61, "kept": 61, "sql_conn": 61, "sql_alchemy_conn": 61, "mount_fil": 61, "read_onli": 61, "config_map_ref": 61, "v1configmapenvsourc": 61, "persistent_volume_claim": 61, "v1persistentvolumeclaimvolumesourc": 61, "claim_nam": 61, "container_port": 61, "80": 61, "key1": 61, "value1": 61, "key2": 61, "value2": 61, "node_affin": 61, "v1nodeaffin": 61, "preferred_during_scheduling_ignored_during_execut": 61, "v1preferredschedulingterm": 61, "weight": 61, "prefer": 61, "v1nodeselectorterm": 61, "match_express": 61, "v1nodeselectorrequir": 61, "disktyp": 61, "ssd": 61, "pod_affin": 61, "v1podaffin": 61, "required_during_scheduling_ignored_during_execut": 61, "v1weightedpodaffinityterm": 61, "pod_affinity_term": 61, "v1podaffinityterm": 61, "v1labelselectorrequir": 61, "s1": 61, "topology_kei": 61, "domain": 61, "beta": 61, "zone": 61, "substitut": 61, "equival": 61, "publicli": 61, "dockerhub": 61, "ecr": 61, "gcr": 61, "quai": 61, "testquai": 61, "usernam": 61, "profil": 61, "password": 61, "Then": 61, "quay_k8": 61, "pwd": 61, "quay_k8s_async": 61, "kubernetes_private_img_task_async": 61, "displai": 61, "kubernetes_task_async_log": 61, "astro_k8s_test_pod": 61, "ne": 61, "mkdir": 61, "p": 61, "afternoon": 61, "alongsid": 61, "invalid": 61, "write_xcom": 61, "sh": 61, "pod_task_xcom_result": 61, "bashoper": 61, "bash_command": 61, "xcom_pul": 61, "write_xcom_async": 61, "kubernetes_write_xcom_task_async": 61, "pod_task_xcom_result_async": 61, "test_error_messag": 61, "world": 61, "email_on_failur": 61, "async_k8": 61, "mycallback": 61, "staticmethod": 61, "create_namespaced_servic": 61, "v1servic": 61, "owner_refer": 61, "v1ownerrefer": 61, "uid": 61, "block_owner_delet": 61, "v1servicespec": 61, "v1serviceport": 61, "target_port": 61, "test_callback": 61, "submiss": 61, "box": 61, "subsequ": 61, "progress": 61, "succe": 61, "serv": 61, "sampl": 61, "spark_job_templ": 61, "apigroup": 61, "pythonvers": 61, "sparkvers": 61, "successfulrunhistorylimit": 61, "hadoopconf": 61, "imagepullsecret": 61, "dynamicalloc": 61, "initialexecutor": 61, "minexecutor": 61, "maxexecutor": 61, "gpu": 61, "null": 61, "quantiti": 61, "cpu": 61, "test_nam": 61, "test_valu": 61, "mongo": 61, "karpent": 61, "provision": 61, "nodeaffin": 61, "requiredduringschedulingignoredduringexecut": 61, "nodeselectorterm": 61, "matchexpress": 61, "r5": 61, "xlarg": 61, "podaffin": 61, "podantiaffin": 61, "taint": 61, "noschedul": 61, "config_map_mount": 61, "snowflak": 61, "mnt": 61, "storag": 61, "from_env_config_map": 61, "configmap_1": 61, "configmap_2": 61, "from_env_secret": 61, "secret_1": 61, "secret_2": 61, "kube_config_fil": 61, "categori": 61, "segment": 61, "encompass": 61, "extern": 61, "s3": 61, "bucket": 61, "spark_task": 61, "OR": 61, "altern": 61, "hsaljoog": 61, "apart": 61, "emploi": 61, "kjo": 61, "perl": 61, "34": 61, "mbignum": 61, "bpi": 61, "wle": 61, "2000": 61, "k8s_job_def": 61, "activedeadlinesecond": 61, "backofflimit": 61, "delete_job_task": 61, "update_job": 61, "vulner": 62, "develop": 62, "branch": 62, "semver": 62, "scope": 62, "break": 62, "patchlevel": 62, "critic": 62, "band": 62, "stakehold": 62, "might": 62, "cherri": 62, "pick": 62, "older": 62, "mix": 62, "govern": 62, "interest": 62, "parti": 62}, "objects": {"airflow.providers.cncf": [[10, 0, 0, "-", "kubernetes"]], "airflow.providers.cncf.kubernetes": [[10, 1, 1, "", "__version__"], [0, 0, 0, "-", "callbacks"], [1, 0, 0, "-", "decorators"], [3, 0, 0, "-", "executors"], [8, 0, 0, "-", "hooks"], [11, 0, 0, "-", "k8s_model"], [12, 0, 0, "-", "kube_client"], [13, 0, 0, "-", "kube_config"], [14, 0, 0, "-", "kubernetes_executor_templates"], [15, 0, 0, "-", "kubernetes_helper_functions"], [17, 0, 0, "-", "operators"], [23, 0, 0, "-", "pod_generator"], [24, 0, 0, "-", "pod_generator_deprecated"], [25, 0, 0, "-", "pod_launcher_deprecated"], [26, 0, 0, "-", "pod_template_file_examples"], [27, 0, 0, "-", "python_kubernetes_script"], [30, 0, 0, "-", "resource_convert"], [32, 0, 0, "-", "secret"], [33, 0, 0, "-", "sensors"], [35, 0, 0, "-", "template_rendering"], [36, 0, 0, "-", "triggers"], [41, 0, 0, "-", "utils"]], "airflow.providers.cncf.kubernetes.callbacks": [[0, 2, 1, "", "ExecutionMode"], [0, 2, 1, "", "KubernetesPodOperatorCallback"], [0, 1, 1, "", "client_type"]], "airflow.providers.cncf.kubernetes.callbacks.ExecutionMode": [[0, 3, 1, "", "ASYNC"], [0, 3, 1, "", "SYNC"]], "airflow.providers.cncf.kubernetes.callbacks.KubernetesPodOperatorCallback": [[0, 4, 1, "", "on_operator_resuming"], [0, 4, 1, "", "on_pod_cleanup"], [0, 4, 1, "", "on_pod_completion"], [0, 4, 1, "", "on_pod_creation"], [0, 4, 1, "", "on_pod_starting"], [0, 4, 1, "", "on_sync_client_creation"], [0, 4, 1, "", "progress_callback"]], "airflow.providers.cncf.kubernetes.decorators": [[2, 0, 0, "-", "kubernetes"]], "airflow.providers.cncf.kubernetes.decorators.kubernetes": [[2, 5, 1, "", "kubernetes_task"]], "airflow.providers.cncf.kubernetes.executors": [[4, 0, 0, "-", "kubernetes_executor"], [5, 0, 0, "-", "kubernetes_executor_types"], [6, 0, 0, "-", "kubernetes_executor_utils"], [7, 0, 0, "-", "local_kubernetes_executor"]], "airflow.providers.cncf.kubernetes.executors.kubernetes_executor": [[4, 1, 1, "", "ARG_MIN_PENDING_MINUTES"], [4, 1, 1, "", "ARG_NAMESPACE"], [4, 1, 1, "", "KUBERNETES_COMMANDS"], [4, 2, 1, "", "KubernetesExecutor"], [4, 1, 1, "", "base_version"]], "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KubernetesExecutor": [[4, 3, 1, "", "RUNNING_POD_LOG_LINES"], [4, 4, 1, "", "adopt_launched_task"], [4, 4, 1, "", "cleanup_stuck_queued_tasks"], [4, 4, 1, "", "clear_not_launched_queued_tasks"], [4, 4, 1, "", "end"], [4, 4, 1, "", "execute_async"], [4, 4, 1, "", "get_cli_commands"], [4, 4, 1, "", "get_task_log"], [4, 4, 1, "", "start"], [4, 3, 1, "", "supports_ad_hoc_ti_run"], [4, 4, 1, "", "sync"], [4, 4, 1, "", "terminate"], [4, 4, 1, "", "try_adopt_task_instances"]], "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types": [[5, 1, 1, "", "ADOPTED"], [5, 1, 1, "", "ALL_NAMESPACES"], [5, 1, 1, "", "KubernetesJobType"], [5, 1, 1, "", "POD_EXECUTOR_DONE_KEY"]], "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils": [[6, 2, 1, "", "AirflowKubernetesScheduler"], [6, 2, 1, "", "KubernetesJobWatcher"], [6, 2, 1, "", "ResourceVersion"], [6, 2, 1, "", "Singleton"], [6, 1, 1, "", "T"], [6, 5, 1, "", "get_base_pod_from_template"]], "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.AirflowKubernetesScheduler": [[6, 4, 1, "", "delete_pod"], [6, 4, 1, "", "patch_pod_executor_done"], [6, 4, 1, "", "process_watcher_task"], [6, 4, 1, "", "run_next"], [6, 4, 1, "", "run_pod_async"], [6, 4, 1, "", "sync"], [6, 4, 1, "", "terminate"]], "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.KubernetesJobWatcher": [[6, 4, 1, "", "process_error"], [6, 4, 1, "", "process_status"], [6, 4, 1, "", "run"]], "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.ResourceVersion": [[6, 3, 1, "", "resource_version"]], "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.Singleton": [[6, 4, 1, "", "__call__"]], "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor": [[7, 2, 1, "", "LocalKubernetesExecutor"]], "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor": [[7, 3, 1, "", "KUBERNETES_QUEUE"], [7, 3, 1, "", "callback_sink"], [7, 3, 1, "", "change_sensor_mode_to_reschedule"], [7, 4, 1, "", "cleanup_stuck_queued_tasks"], [7, 4, 1, "", "debug_dump"], [7, 4, 1, "", "end"], [7, 4, 1, "", "get_cli_commands"], [7, 4, 1, "", "get_event_buffer"], [7, 4, 1, "", "get_task_log"], [7, 4, 1, "", "has_task"], [7, 4, 1, "", "heartbeat"], [7, 3, 1, "", "is_local"], [7, 3, 1, "", "is_production"], [7, 3, 1, "", "is_single_threaded"], [7, 6, 1, "", "job_id"], [7, 4, 1, "", "queue_command"], [7, 4, 1, "", "queue_task_instance"], [7, 6, 1, "", "queued_tasks"], [7, 6, 1, "", "running"], [7, 4, 1, "", "send_callback"], [7, 3, 1, "", "serve_logs"], [7, 6, 1, "", "slots_available"], [7, 4, 1, "", "start"], [7, 3, 1, "", "supports_ad_hoc_ti_run"], [7, 3, 1, "", "supports_pickling"], [7, 3, 1, "", "supports_sentry"], [7, 4, 1, "", "terminate"], [7, 4, 1, "", "try_adopt_task_instances"]], "airflow.providers.cncf.kubernetes.hooks": [[9, 0, 0, "-", "kubernetes"]], "airflow.providers.cncf.kubernetes.hooks.kubernetes": [[9, 2, 1, "", "AsyncKubernetesHook"], [9, 1, 1, "", "JOB_FINAL_STATUS_CONDITION_TYPES"], [9, 1, 1, "", "JOB_STATUS_CONDITION_TYPES"], [9, 2, 1, "", "KubernetesHook"], [9, 1, 1, "", "LOADING_KUBE_CONFIG_FILE_RESOURCE"]], "airflow.providers.cncf.kubernetes.hooks.kubernetes.AsyncKubernetesHook": [[9, 4, 1, "", "delete_pod"], [9, 4, 1, "", "get_conn"], [9, 4, 1, "", "get_conn_extras"], [9, 4, 1, "", "get_job_status"], [9, 4, 1, "", "get_pod"], [9, 4, 1, "", "read_logs"], [9, 4, 1, "", "wait_until_job_complete"]], "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook": [[9, 3, 1, "", "DEFAULT_NAMESPACE"], [9, 4, 1, "", "api_client"], [9, 4, 1, "", "apps_v1_client"], [9, 4, 1, "", "batch_v1_client"], [9, 4, 1, "", "conn_extras"], [9, 3, 1, "", "conn_name_attr"], [9, 3, 1, "", "conn_type"], [9, 4, 1, "", "core_v1_client"], [9, 4, 1, "", "create_custom_object"], [9, 4, 1, "", "create_job"], [9, 4, 1, "", "custom_object_client"], [9, 3, 1, "", "default_conn_name"], [9, 4, 1, "", "delete_custom_object"], [9, 4, 1, "", "get_conn"], [9, 4, 1, "", "get_connection"], [9, 4, 1, "", "get_connection_form_widgets"], [9, 4, 1, "", "get_custom_object"], [9, 4, 1, "", "get_deployment_status"], [9, 4, 1, "", "get_job"], [9, 4, 1, "", "get_job_status"], [9, 4, 1, "", "get_namespace"], [9, 4, 1, "", "get_namespaced_pod_list"], [9, 4, 1, "", "get_pod"], [9, 4, 1, "", "get_pod_log_stream"], [9, 4, 1, "", "get_pod_logs"], [9, 4, 1, "", "get_ui_field_behaviour"], [9, 4, 1, "", "get_xcom_sidecar_container_image"], [9, 4, 1, "", "get_xcom_sidecar_container_resources"], [9, 3, 1, "", "hook_name"], [9, 6, 1, "", "is_in_cluster"], [9, 4, 1, "", "is_job_complete"], [9, 4, 1, "", "is_job_failed"], [9, 4, 1, "", "is_job_successful"], [9, 4, 1, "", "list_jobs_all_namespaces"], [9, 4, 1, "", "list_jobs_from_namespace"], [9, 4, 1, "", "patch_namespaced_job"], [9, 4, 1, "", "wait_until_job_complete"]], "airflow.providers.cncf.kubernetes.k8s_model": [[11, 2, 1, "", "K8SModel"], [11, 5, 1, "", "append_to_pod"]], "airflow.providers.cncf.kubernetes.k8s_model.K8SModel": [[11, 4, 1, "", "attach_to_pod"]], "airflow.providers.cncf.kubernetes.kube_client": [[12, 5, 1, "", "get_kube_client"], [12, 1, 1, "", "has_kubernetes"], [12, 1, 1, "", "log"]], "airflow.providers.cncf.kubernetes.kube_config": [[13, 2, 1, "", "KubeConfig"]], "airflow.providers.cncf.kubernetes.kube_config.KubeConfig": [[13, 3, 1, "", "core_section"], [13, 3, 1, "", "kubernetes_section"], [13, 3, 1, "", "logging_section"]], "airflow.providers.cncf.kubernetes.kubernetes_helper_functions": [[15, 1, 1, "", "POD_NAME_MAX_LENGTH"], [15, 1, 1, "", "alphanum_lower"], [15, 5, 1, "", "annotations_for_logging_task_metadata"], [15, 5, 1, "", "annotations_to_key"], [15, 5, 1, "", "create_pod_id"], [15, 5, 1, "", "create_unique_id"], [15, 5, 1, "", "get_logs_task_metadata"], [15, 1, 1, "", "log"]], "airflow.providers.cncf.kubernetes.operators": [[16, 0, 0, "-", "custom_object_launcher"], [18, 0, 0, "-", "job"], [19, 0, 0, "-", "kubernetes_pod"], [20, 0, 0, "-", "pod"], [21, 0, 0, "-", "resource"], [22, 0, 0, "-", "spark_kubernetes"]], "airflow.providers.cncf.kubernetes.operators.custom_object_launcher": [[16, 2, 1, "", "CustomObjectLauncher"], [16, 2, 1, "", "CustomObjectStatus"], [16, 2, 1, "", "KubernetesSpec"], [16, 2, 1, "", "SparkJobSpec"], [16, 2, 1, "", "SparkResources"], [16, 5, 1, "", "should_retry_start_spark_job"]], "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.CustomObjectLauncher": [[16, 4, 1, "", "check_pod_start_failure"], [16, 4, 1, "", "delete_spark_job"], [16, 4, 1, "", "get_body"], [16, 4, 1, "", "pod_manager"], [16, 4, 1, "", "spark_job_not_running"], [16, 4, 1, "", "start_spark_job"]], "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.CustomObjectStatus": [[16, 3, 1, "", "FAILED"], [16, 3, 1, "", "RUNNING"], [16, 3, 1, "", "SUBMITTED"], [16, 3, 1, "", "SUCCEEDED"]], "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.KubernetesSpec": [[16, 4, 1, "", "set_attribute"]], "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.SparkJobSpec": [[16, 4, 1, "", "update_resources"], [16, 4, 1, "", "validate"]], "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.SparkResources": [[16, 4, 1, "", "convert_resources"], [16, 6, 1, "", "driver_resources"], [16, 6, 1, "", "executor_resources"], [16, 6, 1, "", "resources"]], "airflow.providers.cncf.kubernetes.operators.job": [[18, 2, 1, "", "KubernetesDeleteJobOperator"], [18, 2, 1, "", "KubernetesJobOperator"], [18, 2, 1, "", "KubernetesPatchJobOperator"], [18, 1, 1, "", "log"]], "airflow.providers.cncf.kubernetes.operators.job.KubernetesDeleteJobOperator": [[18, 4, 1, "", "client"], [18, 4, 1, "", "execute"], [18, 4, 1, "", "hook"], [18, 3, 1, "", "template_fields"]], "airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator": [[18, 4, 1, "", "build_job_request_obj"], [18, 4, 1, "", "client"], [18, 4, 1, "", "create_job"], [18, 4, 1, "", "deserialize_job_template_file"], [18, 4, 1, "", "execute"], [18, 4, 1, "", "execute_complete"], [18, 4, 1, "", "execute_deferrable"], [18, 4, 1, "", "hook"], [18, 4, 1, "", "on_kill"], [18, 4, 1, "", "reconcile_job_specs"], [18, 4, 1, "", "reconcile_jobs"], [18, 3, 1, "", "template_fields"]], "airflow.providers.cncf.kubernetes.operators.job.KubernetesPatchJobOperator": [[18, 4, 1, "", "execute"], [18, 4, 1, "", "hook"], [18, 3, 1, "", "template_fields"]], "airflow.providers.cncf.kubernetes.operators.pod": [[20, 1, 1, "", "KUBE_CONFIG_ENV_VAR"], [20, 2, 1, "", "KubernetesPodOperator"], [20, 2, 1, "", "PodEventType"], [20, 7, 1, "", "PodReattachFailure"], [20, 1, 1, "", "alphanum_lower"]], "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator": [[20, 3, 1, "", "BASE_CONTAINER_NAME"], [20, 3, 1, "", "ISTIO_CONTAINER_NAME"], [20, 3, 1, "", "KILL_ISTIO_PROXY_SUCCESS_MSG"], [20, 3, 1, "", "POD_CHECKED_KEY"], [20, 3, 1, "", "POST_TERMINATION_TIMEOUT"], [20, 4, 1, "", "await_pod_start"], [20, 4, 1, "", "build_pod_request_obj"], [20, 4, 1, "", "cleanup"], [20, 4, 1, "", "client"], [20, 4, 1, "", "dry_run"], [20, 4, 1, "", "execute"], [20, 4, 1, "", "execute_async"], [20, 4, 1, "", "execute_complete"], [20, 4, 1, "", "execute_sync"], [20, 4, 1, "", "extract_xcom"], [20, 4, 1, "", "find_pod"], [20, 4, 1, "", "get_or_create_pod"], [20, 4, 1, "", "hook"], [20, 4, 1, "", "invoke_defer_method"], [20, 4, 1, "", "is_istio_enabled"], [20, 4, 1, "", "kill_istio_sidecar"], [20, 4, 1, "", "on_kill"], [20, 4, 1, "", "patch_already_checked"], [20, 4, 1, "", "pod_manager"], [20, 4, 1, "", "post_complete_action"], [20, 4, 1, "", "process_pod_deletion"], [20, 3, 1, "", "template_fields"], [20, 3, 1, "", "template_fields_renderers"], [20, 4, 1, "", "trigger_reentry"], [20, 4, 1, "", "write_logs"]], "airflow.providers.cncf.kubernetes.operators.pod.PodEventType": [[20, 3, 1, "", "NORMAL"], [20, 3, 1, "", "WARNING"]], "airflow.providers.cncf.kubernetes.operators.resource": [[21, 2, 1, "", "KubernetesCreateResourceOperator"], [21, 2, 1, "", "KubernetesDeleteResourceOperator"]], "airflow.providers.cncf.kubernetes.operators.resource.KubernetesCreateResourceOperator": [[21, 4, 1, "", "create_custom_from_yaml_object"], [21, 4, 1, "", "execute"]], "airflow.providers.cncf.kubernetes.operators.resource.KubernetesDeleteResourceOperator": [[21, 4, 1, "", "delete_custom_from_yaml_object"], [21, 4, 1, "", "execute"]], "airflow.providers.cncf.kubernetes.operators.spark_kubernetes": [[22, 2, 1, "", "SparkKubernetesOperator"]], "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator": [[22, 3, 1, "", "BASE_CONTAINER_NAME"], [22, 4, 1, "", "client"], [22, 4, 1, "", "create_job_name"], [22, 4, 1, "", "create_labels_for_pod"], [22, 4, 1, "", "custom_obj_api"], [22, 4, 1, "", "dry_run"], [22, 4, 1, "", "execute"], [22, 4, 1, "", "find_spark_job"], [22, 4, 1, "", "get_or_create_spark_crd"], [22, 4, 1, "", "hook"], [22, 4, 1, "", "manage_template_specs"], [22, 4, 1, "", "on_kill"], [22, 4, 1, "", "patch_already_checked"], [22, 4, 1, "", "pod_manager"], [22, 4, 1, "", "process_pod_deletion"], [22, 6, 1, "", "template_body"], [22, 3, 1, "", "template_ext"], [22, 3, 1, "", "template_fields"], [22, 3, 1, "", "template_fields_renderers"], [22, 3, 1, "", "ui_color"]], "airflow.providers.cncf.kubernetes.pod_generator": [[23, 1, 1, "", "MAX_LABEL_LEN"], [23, 2, 1, "", "PodGenerator"], [23, 7, 1, "", "PodMutationHookException"], [23, 7, 1, "", "PodReconciliationError"], [23, 5, 1, "", "datetime_to_label_safe_datestring"], [23, 5, 1, "", "extend_object_field"], [23, 5, 1, "", "label_safe_datestring_to_datetime"], [23, 1, 1, "", "log"], [23, 5, 1, "", "make_safe_label_value"], [23, 5, 1, "", "merge_objects"]], "airflow.providers.cncf.kubernetes.pod_generator.PodGenerator": [[23, 4, 1, "", "add_xcom_sidecar"], [23, 4, 1, "", "construct_pod"], [23, 4, 1, "", "deserialize_model_dict"], [23, 4, 1, "", "deserialize_model_file"], [23, 4, 1, "", "from_legacy_obj"], [23, 4, 1, "", "from_obj"], [23, 4, 1, "", "gen_pod"], [23, 4, 1, "", "make_unique_pod_id"], [23, 4, 1, "", "reconcile_containers"], [23, 4, 1, "", "reconcile_metadata"], [23, 4, 1, "", "reconcile_pods"], [23, 4, 1, "", "reconcile_specs"], [23, 4, 1, "", "serialize_pod"]], "airflow.providers.cncf.kubernetes.pod_generator_deprecated": [[24, 1, 1, "", "MAX_LABEL_LEN"], [24, 1, 1, "", "MAX_POD_ID_LEN"], [24, 2, 1, "", "PodDefaults"], [24, 2, 1, "", "PodGenerator"], [24, 5, 1, "", "make_safe_label_value"]], "airflow.providers.cncf.kubernetes.pod_generator_deprecated.PodDefaults": [[24, 3, 1, "", "SIDECAR_CONTAINER"], [24, 3, 1, "", "SIDECAR_CONTAINER_NAME"], [24, 3, 1, "", "VOLUME"], [24, 3, 1, "", "VOLUME_MOUNT"], [24, 3, 1, "", "XCOM_CMD"], [24, 3, 1, "", "XCOM_MOUNT_PATH"]], "airflow.providers.cncf.kubernetes.pod_generator_deprecated.PodGenerator": [[24, 4, 1, "", "add_sidecar"], [24, 4, 1, "", "from_obj"], [24, 4, 1, "", "gen_pod"], [24, 4, 1, "", "make_unique_pod_id"]], "airflow.providers.cncf.kubernetes.pod_launcher_deprecated": [[25, 2, 1, "", "PodLauncher"], [25, 2, 1, "", "PodStatus"]], "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodLauncher": [[25, 4, 1, "", "base_container_is_running"], [25, 4, 1, "", "delete_pod"], [25, 4, 1, "", "monitor_pod"], [25, 4, 1, "", "parse_log_line"], [25, 4, 1, "", "pod_is_running"], [25, 4, 1, "", "pod_not_started"], [25, 4, 1, "", "process_status"], [25, 4, 1, "", "read_pod"], [25, 4, 1, "", "read_pod_events"], [25, 4, 1, "", "read_pod_logs"], [25, 4, 1, "", "run_pod_async"], [25, 4, 1, "", "start_pod"]], "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodStatus": [[25, 3, 1, "", "FAILED"], [25, 3, 1, "", "PENDING"], [25, 3, 1, "", "RUNNING"], [25, 3, 1, "", "SUCCEEDED"]], "airflow.providers.cncf.kubernetes.python_kubernetes_script": [[27, 5, 1, "", "remove_task_decorator"], [27, 5, 1, "", "write_python_script"]], "airflow.providers.cncf.kubernetes.resource_convert": [[28, 0, 0, "-", "configmap"], [29, 0, 0, "-", "env_variable"], [31, 0, 0, "-", "secret"]], "airflow.providers.cncf.kubernetes.resource_convert.configmap": [[28, 5, 1, "", "convert_configmap"], [28, 5, 1, "", "convert_configmap_to_volume"]], "airflow.providers.cncf.kubernetes.resource_convert.env_variable": [[29, 5, 1, "", "convert_env_vars"]], "airflow.providers.cncf.kubernetes.resource_convert.secret": [[31, 5, 1, "", "convert_image_pull_secrets"], [31, 5, 1, "", "convert_secret"]], "airflow.providers.cncf.kubernetes.secret": [[32, 2, 1, "", "Secret"]], "airflow.providers.cncf.kubernetes.secret.Secret": [[32, 4, 1, "", "__eq__"], [32, 4, 1, "", "__repr__"], [32, 4, 1, "", "attach_to_pod"], [32, 4, 1, "", "to_env_from_secret"], [32, 4, 1, "", "to_env_secret"], [32, 4, 1, "", "to_volume_secret"]], "airflow.providers.cncf.kubernetes.sensors": [[34, 0, 0, "-", "spark_kubernetes"]], "airflow.providers.cncf.kubernetes.sensors.spark_kubernetes": [[34, 2, 1, "", "SparkKubernetesSensor"]], "airflow.providers.cncf.kubernetes.sensors.spark_kubernetes.SparkKubernetesSensor": [[34, 3, 1, "", "FAILURE_STATES"], [34, 3, 1, "", "SUCCESS_STATES"], [34, 4, 1, "", "hook"], [34, 4, 1, "", "poke"], [34, 3, 1, "", "template_fields"]], "airflow.providers.cncf.kubernetes.template_rendering": [[35, 5, 1, "", "get_rendered_k8s_spec"], [35, 5, 1, "", "render_k8s_pod_yaml"]], "airflow.providers.cncf.kubernetes.triggers": [[37, 0, 0, "-", "job"], [38, 0, 0, "-", "kubernetes_pod"], [39, 0, 0, "-", "pod"]], "airflow.providers.cncf.kubernetes.triggers.job": [[37, 2, 1, "", "KubernetesJobTrigger"]], "airflow.providers.cncf.kubernetes.triggers.job.KubernetesJobTrigger": [[37, 4, 1, "", "hook"], [37, 4, 1, "", "run"], [37, 4, 1, "", "serialize"]], "airflow.providers.cncf.kubernetes.triggers.pod": [[39, 2, 1, "", "ContainerState"], [39, 2, 1, "", "KubernetesPodTrigger"]], "airflow.providers.cncf.kubernetes.triggers.pod.ContainerState": [[39, 3, 1, "", "FAILED"], [39, 3, 1, "", "RUNNING"], [39, 3, 1, "", "TERMINATED"], [39, 3, 1, "", "UNDEFINED"], [39, 3, 1, "", "WAITING"]], "airflow.providers.cncf.kubernetes.triggers.pod.KubernetesPodTrigger": [[39, 4, 1, "", "define_container_state"], [39, 4, 1, "", "hook"], [39, 4, 1, "", "run"], [39, 4, 1, "", "serialize"], [39, 4, 1, "", "should_wait"]], "airflow.providers.cncf.kubernetes.utils": [[40, 0, 0, "-", "delete_from"], [42, 0, 0, "-", "k8s_resource_iterator"], [43, 0, 0, "-", "pod_manager"], [44, 0, 0, "-", "xcom_sidecar"]], "airflow.providers.cncf.kubernetes.utils.delete_from": [[40, 1, 1, "", "DEFAULT_DELETION_BODY"], [40, 7, 1, "", "FailToDeleteError"], [40, 5, 1, "", "delete_from_dict"], [40, 5, 1, "", "delete_from_yaml"]], "airflow.providers.cncf.kubernetes.utils.delete_from.FailToDeleteError": [[40, 4, 1, "", "__str__"]], "airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator": [[42, 5, 1, "", "k8s_resource_iterator"]], "airflow.providers.cncf.kubernetes.utils.pod_manager": [[43, 2, 1, "", "OnFinishAction"], [43, 7, 1, "", "PodLaunchFailedException"], [43, 7, 1, "", "PodLaunchTimeoutException"], [43, 2, 1, "", "PodLoggingStatus"], [43, 2, 1, "", "PodManager"], [43, 7, 1, "", "PodNotFoundException"], [43, 2, 1, "", "PodOperatorHookProtocol"], [43, 2, 1, "", "PodPhase"], [43, 5, 1, "", "container_is_completed"], [43, 5, 1, "", "container_is_running"], [43, 5, 1, "", "container_is_succeeded"], [43, 5, 1, "", "container_is_terminated"], [43, 5, 1, "", "get_container_status"], [43, 5, 1, "", "get_container_termination_message"], [43, 5, 1, "", "should_retry_start_pod"]], "airflow.providers.cncf.kubernetes.utils.pod_manager.OnFinishAction": [[43, 3, 1, "", "DELETE_POD"], [43, 3, 1, "", "DELETE_SUCCEEDED_POD"], [43, 3, 1, "", "KEEP_POD"]], "airflow.providers.cncf.kubernetes.utils.pod_manager.PodLoggingStatus": [[43, 3, 1, "", "last_log_time"], [43, 3, 1, "", "running"]], "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager": [[43, 4, 1, "", "await_container_completion"], [43, 4, 1, "", "await_pod_completion"], [43, 4, 1, "", "await_pod_start"], [43, 4, 1, "", "await_xcom_sidecar_container_start"], [43, 4, 1, "", "container_is_running"], [43, 4, 1, "", "container_is_terminated"], [43, 4, 1, "", "create_pod"], [43, 4, 1, "", "delete_pod"], [43, 4, 1, "", "extract_xcom"], [43, 4, 1, "", "extract_xcom_json"], [43, 4, 1, "", "extract_xcom_kill"], [43, 4, 1, "", "follow_container_logs"], [43, 4, 1, "", "get_container_names"], [43, 4, 1, "", "parse_log_line"], [43, 4, 1, "", "read_pod"], [43, 4, 1, "", "read_pod_events"], [43, 4, 1, "", "read_pod_logs"], [43, 4, 1, "", "run_pod_async"]], "airflow.providers.cncf.kubernetes.utils.pod_manager.PodOperatorHookProtocol": [[43, 6, 1, "", "core_v1_client"], [43, 4, 1, "", "get_namespace"], [43, 4, 1, "", "get_pod"], [43, 4, 1, "", "get_xcom_sidecar_container_image"], [43, 4, 1, "", "get_xcom_sidecar_container_resources"], [43, 6, 1, "", "is_in_cluster"]], "airflow.providers.cncf.kubernetes.utils.pod_manager.PodPhase": [[43, 3, 1, "", "FAILED"], [43, 3, 1, "", "PENDING"], [43, 3, 1, "", "RUNNING"], [43, 3, 1, "", "SUCCEEDED"], [43, 3, 1, "", "terminal_states"]], "airflow.providers.cncf.kubernetes.utils.xcom_sidecar": [[44, 2, 1, "", "PodDefaults"], [44, 5, 1, "", "add_xcom_sidecar"]], "airflow.providers.cncf.kubernetes.utils.xcom_sidecar.PodDefaults": [[44, 3, 1, "", "SIDECAR_CONTAINER"], [44, 3, 1, "", "SIDECAR_CONTAINER_NAME"], [44, 3, 1, "", "VOLUME"], [44, 3, 1, "", "VOLUME_MOUNT"], [44, 3, 1, "", "XCOM_CMD"], [44, 3, 1, "", "XCOM_MOUNT_PATH"]], "tests.system.providers.cncf": [[51, 0, 0, "-", "kubernetes"]], "tests.system.providers.cncf.kubernetes": [[45, 0, 0, "-", "example_kubernetes"], [46, 0, 0, "-", "example_kubernetes_async"], [47, 0, 0, "-", "example_kubernetes_decorator"], [48, 0, 0, "-", "example_kubernetes_job"], [49, 0, 0, "-", "example_kubernetes_resource"], [50, 0, 0, "-", "example_spark_kubernetes"]], "tests.system.providers.cncf.kubernetes.example_kubernetes": [[45, 1, 1, "", "DAG_ID"], [45, 1, 1, "", "ENV_ID"], [45, 1, 1, "", "affinity"], [45, 1, 1, "", "configmaps"], [45, 1, 1, "", "init_container"], [45, 1, 1, "", "init_container_volume_mounts"], [45, 1, 1, "", "init_environments"], [45, 1, 1, "", "k"], [45, 1, 1, "", "port"], [45, 1, 1, "", "secret_all_keys"], [45, 1, 1, "", "secret_env"], [45, 1, 1, "", "secret_file"], [45, 1, 1, "", "test_run"], [45, 1, 1, "", "tolerations"], [45, 1, 1, "", "volume"], [45, 1, 1, "", "volume_mount"]], "tests.system.providers.cncf.kubernetes.example_kubernetes_async": [[46, 1, 1, "", "DAG_ID"], [46, 1, 1, "", "ENV_ID"], [46, 1, 1, "", "affinity"], [46, 1, 1, "", "configmaps"], [46, 1, 1, "", "init_container"], [46, 1, 1, "", "init_container_volume_mounts"], [46, 1, 1, "", "init_environments"], [46, 1, 1, "", "k"], [46, 1, 1, "", "port"], [46, 1, 1, "", "secret_all_keys"], [46, 1, 1, "", "secret_env"], [46, 1, 1, "", "secret_file"], [46, 1, 1, "", "test_run"], [46, 1, 1, "", "tolerations"], [46, 1, 1, "", "volume"], [46, 1, 1, "", "volume_mount"]], "tests.system.providers.cncf.kubernetes.example_kubernetes_decorator": [[47, 5, 1, "", "execute_in_k8s_pod"], [47, 1, 1, "", "test_run"]], "tests.system.providers.cncf.kubernetes.example_kubernetes_job": [[48, 1, 1, "", "DAG_ID"], [48, 1, 1, "", "ENV_ID"], [48, 1, 1, "", "JOB_NAME"], [48, 1, 1, "", "JOB_NAMESPACE"], [48, 1, 1, "", "k8s_job"], [48, 1, 1, "", "test_run"]], "tests.system.providers.cncf.kubernetes.example_kubernetes_resource": [[49, 1, 1, "", "DAG_ID"], [49, 1, 1, "", "ENV_ID"], [49, 1, 1, "", "pvc_conf"], [49, 1, 1, "", "pvc_name"], [49, 1, 1, "", "t1"], [49, 1, 1, "", "test_run"]], "tests.system.providers.cncf.kubernetes.example_spark_kubernetes": [[50, 1, 1, "", "DAG_ID"], [50, 1, 1, "", "ENV_ID"], [50, 1, 1, "", "pi_example_path"], [50, 1, 1, "", "test_run"]]}, "objtypes": {"0": "py:module", "1": "py:data", "2": "py:class", "3": "py:attribute", "4": "py:method", "5": "py:function", "6": "py:property", "7": "py:exception"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "data", "Python data"], "2": ["py", "class", "Python class"], "3": ["py", "attribute", "Python attribute"], "4": ["py", "method", "Python method"], "5": ["py", "function", "Python function"], "6": ["py", "property", "Python property"], "7": ["py", "exception", "Python exception"]}, "titleterms": {"airflow": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 54, 57], "provid": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 54, 57], "cncf": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 54, 57], "kubernet": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 56, 57, 59, 61], "callback": [0, 61], "modul": [0, 2, 4, 5, 6, 7, 9, 11, 12, 13, 15, 16, 18, 20, 21, 22, 23, 24, 25, 27, 28, 29, 31, 32, 34, 35, 37, 39, 40, 42, 43, 44, 45, 46, 47, 48, 49, 50], "content": [0, 2, 4, 5, 6, 7, 9, 10, 11, 12, 13, 15, 16, 18, 20, 21, 22, 23, 24, 25, 27, 28, 29, 31, 32, 34, 35, 37, 39, 40, 42, 43, 44, 45, 46, 47, 48, 49, 50, 61], "class": [0, 4, 6, 7, 9, 11, 13, 16, 18, 20, 21, 22, 23, 24, 25, 32, 34, 37, 39, 43, 44], "attribut": [0, 4, 6, 9, 12, 15, 18, 20, 23, 24, 40, 47], "decor": [1, 2], "submodul": [1, 3, 8, 10, 17, 30, 33, 36, 41, 51], "function": [2, 6, 11, 12, 15, 16, 23, 24, 27, 28, 29, 31, 35, 40, 42, 43, 44, 47], "executor": [3, 4, 5, 6, 7, 53, 59, 60], "kubernetes_executor": [4, 55], "kubernetes_executor_typ": 5, "kubernetes_executor_util": 6, "local_kubernetes_executor": [7, 55], "hook": [8, 9], "subpackag": 10, "packag": [10, 54, 57, 58], "k8s_model": 11, "kube_cli": 12, "kube_config": 13, "kubernetes_executor_templ": 14, "kubernetes_helper_funct": 15, "oper": [16, 17, 18, 19, 20, 21, 22, 61], "custom_object_launch": 16, "job": [18, 37], "kubernetes_pod": [19, 38], "pod": [20, 39, 53, 59, 61], "resourc": 21, "spark_kubernet": [22, 34], "pod_gener": 23, "pod_generator_deprec": 24, "pod_launcher_deprec": 25, "pod_template_file_exampl": 26, "python_kubernetes_script": 27, "resource_convert": [28, 29, 30, 31], "configmap": [28, 61], "env_vari": 29, "secret": [31, 32, 61], "sensor": [33, 34], "template_rend": 35, "trigger": [36, 37, 38, 39], "util": [40, 41, 42, 43, 44], "delete_from": 40, "k8s_resource_iter": 42, "pod_manag": 43, "xcom_sidecar": 44, "test": [45, 46, 47, 48, 49, 50, 51], "system": [45, 46, 47, 48, 49, 50, 51], "example_kubernet": 45, "example_kubernetes_async": 46, "example_kubernetes_decor": 47, "example_kubernetes_job": 48, "example_kubernetes_resourc": 49, "example_spark_kubernet": 50, "changelog": 52, "8": [52, 54], "1": [52, 54], "bug": 52, "fix": 52, "0": [52, 54], "featur": 52, "misc": 52, "break": 52, "chang": 52, "7": [52, 54], "14": [52, 54], "13": [52, 54], "12": [52, 54], "11": [52, 54], "10": [52, 54], "9": [52, 54], "6": [52, 54], "5": [52, 54], "4": [52, 54], "2": [52, 54], "3": [52, 54], "new": 52, "deprec": [52, 55], "yank": 52, "paramet": 52, "is_delete_operator_pod": 52, "ha": 52, "default": [52, 56], "note": 52, "kubernetespodoper": [52, 61], "podlaunch": 52, "overview": 52, "detail": 52, "method": 52, "renam": 52, "refactor": 52, "delet": 52, "command": 53, "posit": 53, "argument": [53, 61], "sub": 53, "cleanup": 53, "name": [53, 59], "gener": 53, "dag": [53, 59], "yaml": 53, "apach": [54, 57], "configur": [55, 56, 59], "refer": [55, 61], "section": 55, "api_client_retry_configur": 55, "cluster_context": 55, "config_fil": 55, "delete_option_kwarg": 55, "delete_worker_pod": 55, "delete_worker_pods_on_failur": 55, "enable_tcp_keepal": 55, "in_clust": 55, "kube_client_request_arg": 55, "logs_task_metadata": 55, "multi_namespace_mod": 55, "multi_namespace_mode_namespace_list": 55, "namespac": 55, "pod_template_fil": [55, 59], "ssl_ca_cert": 55, "task_publish_max_retri": 55, "tcp_keep_cnt": 55, "tcp_keep_idl": 55, "tcp_keep_intvl": 55, "verify_ssl": 55, "worker_container_repositori": 55, "worker_container_tag": 55, "worker_pod_pending_fatal_container_state_reason": 55, "worker_pods_creation_batch_s": 55, "worker_pods_queued_check_interv": 55, "worker_pods_pending_timeout": 55, "worker_pods_pending_timeout_check_interv": 55, "kubernetes_queu": 55, "cluster": [56, 61], "connect": 56, "authent": 56, "id": 56, "instal": [57, 58], "requir": 57, "from": 58, "sourc": 58, "releas": [58, 62], "integr": 58, "verifi": 58, "pypi": 58, "base": 59, "imag": [59, 61], "exampl": [59, 61], "templat": 59, "pod_overrid": 59, "manag": 59, "log": 59, "comparison": 59, "celeryexecutor": 59, "fault": 59, "toler": 59, "handl": 59, "worker": 59, "crash": 59, "But": 59, "what": 59, "about": 59, "case": 59, "where": 59, "schedul": 59, "localkubernet": 60, "tabl": 61, "how": 61, "doe": 61, "thi": 61, "work": 61, "debug": 61, "preced": 61, "us": 61, "volum": 61, "differ": 61, "between": 61, "object": 61, "spec": 61, "privat": 61, "contain": 61, "registri": 61, "xcom": 61, "includ": 61, "error": 61, "messag": 61, "email": 61, "alert": 61, "sparkkubernetesoper": 61, "usag": 61, "kubernetesjoboper": 61, "kubernetesdeletejoboper": 61, "kubernetespatchjoboper": 61, "secur": 62, "patch": 62}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.viewcode": 1, "sphinx.ext.intersphinx": 1, "sphinx": 57}, "alltitles": {"airflow.providers.cncf.kubernetes.callbacks": [[0, "module-airflow.providers.cncf.kubernetes.callbacks"]], "Module Contents": [[0, "module-contents"], [2, "module-contents"], [4, "module-contents"], [5, "module-contents"], [6, "module-contents"], [7, "module-contents"], [9, "module-contents"], [11, "module-contents"], [12, "module-contents"], [13, "module-contents"], [15, "module-contents"], [16, "module-contents"], [18, "module-contents"], [20, "module-contents"], [21, "module-contents"], [22, "module-contents"], [23, "module-contents"], [24, "module-contents"], [25, "module-contents"], [27, "module-contents"], [28, "module-contents"], [29, "module-contents"], [31, "module-contents"], [32, "module-contents"], [34, "module-contents"], [35, "module-contents"], [37, "module-contents"], [39, "module-contents"], [40, "module-contents"], [42, "module-contents"], [43, "module-contents"], [44, "module-contents"], [45, "module-contents"], [46, "module-contents"], [47, "module-contents"], [48, "module-contents"], [49, "module-contents"], [50, "module-contents"]], "Classes": [[0, "classes"], [4, "classes"], [6, "classes"], [7, "classes"], [9, "classes"], [11, "classes"], [13, "classes"], [16, "classes"], [18, "classes"], [20, "classes"], [21, "classes"], [22, "classes"], [23, "classes"], [24, "classes"], [25, "classes"], [32, "classes"], [34, "classes"], [37, "classes"], [39, "classes"], [43, "classes"], [44, "classes"]], "Attributes": [[0, "attributes"], [4, "attributes"], [6, "attributes"], [9, "attributes"], [12, "attributes"], [15, "attributes"], [18, "attributes"], [20, "attributes"], [23, "attributes"], [24, "attributes"], [40, "attributes"], [47, "attributes"]], "airflow.providers.cncf.kubernetes.decorators": [[1, "module-airflow.providers.cncf.kubernetes.decorators"]], "Submodules": [[1, "submodules"], [3, "submodules"], [8, "submodules"], [10, "submodules"], [17, "submodules"], [30, "submodules"], [33, "submodules"], [36, "submodules"], [41, "submodules"], [51, "submodules"]], "airflow.providers.cncf.kubernetes.decorators.kubernetes": [[2, "module-airflow.providers.cncf.kubernetes.decorators.kubernetes"]], "Functions": [[2, "functions"], [6, "functions"], [11, "functions"], [12, "functions"], [15, "functions"], [16, "functions"], [23, "functions"], [24, "functions"], [27, "functions"], [28, "functions"], [29, "functions"], [31, "functions"], [35, "functions"], [40, "functions"], [42, "functions"], [43, "functions"], [44, "functions"], [47, "functions"]], "airflow.providers.cncf.kubernetes.executors": [[3, "module-airflow.providers.cncf.kubernetes.executors"]], "airflow.providers.cncf.kubernetes.executors.kubernetes_executor": [[4, "module-airflow.providers.cncf.kubernetes.executors.kubernetes_executor"]], "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types": [[5, "module-airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types"]], "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils": [[6, "module-airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils"]], "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor": [[7, "module-airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor"]], "airflow.providers.cncf.kubernetes.hooks": [[8, "module-airflow.providers.cncf.kubernetes.hooks"]], "airflow.providers.cncf.kubernetes.hooks.kubernetes": [[9, "module-airflow.providers.cncf.kubernetes.hooks.kubernetes"]], "airflow.providers.cncf.kubernetes": [[10, "module-airflow.providers.cncf.kubernetes"]], "Subpackages": [[10, "subpackages"]], "Package Contents": [[10, "package-contents"]], "airflow.providers.cncf.kubernetes.k8s_model": [[11, "module-airflow.providers.cncf.kubernetes.k8s_model"]], "airflow.providers.cncf.kubernetes.kube_client": [[12, "module-airflow.providers.cncf.kubernetes.kube_client"]], "airflow.providers.cncf.kubernetes.kube_config": [[13, "module-airflow.providers.cncf.kubernetes.kube_config"]], "airflow.providers.cncf.kubernetes.kubernetes_executor_templates": [[14, "module-airflow.providers.cncf.kubernetes.kubernetes_executor_templates"]], "airflow.providers.cncf.kubernetes.kubernetes_helper_functions": [[15, "module-airflow.providers.cncf.kubernetes.kubernetes_helper_functions"]], "airflow.providers.cncf.kubernetes.operators.custom_object_launcher": [[16, "module-airflow.providers.cncf.kubernetes.operators.custom_object_launcher"]], "airflow.providers.cncf.kubernetes.operators": [[17, "module-airflow.providers.cncf.kubernetes.operators"]], "airflow.providers.cncf.kubernetes.operators.job": [[18, "module-airflow.providers.cncf.kubernetes.operators.job"]], "airflow.providers.cncf.kubernetes.operators.kubernetes_pod": [[19, "module-airflow.providers.cncf.kubernetes.operators.kubernetes_pod"]], "airflow.providers.cncf.kubernetes.operators.pod": [[20, "module-airflow.providers.cncf.kubernetes.operators.pod"]], "airflow.providers.cncf.kubernetes.operators.resource": [[21, "module-airflow.providers.cncf.kubernetes.operators.resource"]], "airflow.providers.cncf.kubernetes.operators.spark_kubernetes": [[22, "module-airflow.providers.cncf.kubernetes.operators.spark_kubernetes"]], "airflow.providers.cncf.kubernetes.pod_generator": [[23, "module-airflow.providers.cncf.kubernetes.pod_generator"]], "airflow.providers.cncf.kubernetes.pod_generator_deprecated": [[24, "module-airflow.providers.cncf.kubernetes.pod_generator_deprecated"]], "airflow.providers.cncf.kubernetes.pod_launcher_deprecated": [[25, "module-airflow.providers.cncf.kubernetes.pod_launcher_deprecated"]], "airflow.providers.cncf.kubernetes.pod_template_file_examples": [[26, "module-airflow.providers.cncf.kubernetes.pod_template_file_examples"]], "airflow.providers.cncf.kubernetes.python_kubernetes_script": [[27, "module-airflow.providers.cncf.kubernetes.python_kubernetes_script"]], "airflow.providers.cncf.kubernetes.resource_convert.configmap": [[28, "module-airflow.providers.cncf.kubernetes.resource_convert.configmap"]], "airflow.providers.cncf.kubernetes.resource_convert.env_variable": [[29, "module-airflow.providers.cncf.kubernetes.resource_convert.env_variable"]], "airflow.providers.cncf.kubernetes.resource_convert": [[30, "module-airflow.providers.cncf.kubernetes.resource_convert"]], "airflow.providers.cncf.kubernetes.resource_convert.secret": [[31, "module-airflow.providers.cncf.kubernetes.resource_convert.secret"]], "airflow.providers.cncf.kubernetes.secret": [[32, "module-airflow.providers.cncf.kubernetes.secret"]], "airflow.providers.cncf.kubernetes.sensors": [[33, "module-airflow.providers.cncf.kubernetes.sensors"]], "airflow.providers.cncf.kubernetes.sensors.spark_kubernetes": [[34, "module-airflow.providers.cncf.kubernetes.sensors.spark_kubernetes"]], "airflow.providers.cncf.kubernetes.template_rendering": [[35, "module-airflow.providers.cncf.kubernetes.template_rendering"]], "airflow.providers.cncf.kubernetes.triggers": [[36, "module-airflow.providers.cncf.kubernetes.triggers"]], "airflow.providers.cncf.kubernetes.triggers.job": [[37, "module-airflow.providers.cncf.kubernetes.triggers.job"]], "airflow.providers.cncf.kubernetes.triggers.kubernetes_pod": [[38, "module-airflow.providers.cncf.kubernetes.triggers.kubernetes_pod"]], "airflow.providers.cncf.kubernetes.triggers.pod": [[39, "module-airflow.providers.cncf.kubernetes.triggers.pod"]], "airflow.providers.cncf.kubernetes.utils.delete_from": [[40, "module-airflow.providers.cncf.kubernetes.utils.delete_from"]], "airflow.providers.cncf.kubernetes.utils": [[41, "module-airflow.providers.cncf.kubernetes.utils"]], "airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator": [[42, "module-airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator"]], "airflow.providers.cncf.kubernetes.utils.pod_manager": [[43, "module-airflow.providers.cncf.kubernetes.utils.pod_manager"]], "airflow.providers.cncf.kubernetes.utils.xcom_sidecar": [[44, "module-airflow.providers.cncf.kubernetes.utils.xcom_sidecar"]], "tests.system.providers.cncf.kubernetes.example_kubernetes": [[45, "module-tests.system.providers.cncf.kubernetes.example_kubernetes"]], "tests.system.providers.cncf.kubernetes.example_kubernetes_async": [[46, "module-tests.system.providers.cncf.kubernetes.example_kubernetes_async"]], "tests.system.providers.cncf.kubernetes.example_kubernetes_decorator": [[47, "module-tests.system.providers.cncf.kubernetes.example_kubernetes_decorator"]], "tests.system.providers.cncf.kubernetes.example_kubernetes_job": [[48, "module-tests.system.providers.cncf.kubernetes.example_kubernetes_job"]], "tests.system.providers.cncf.kubernetes.example_kubernetes_resource": [[49, "module-tests.system.providers.cncf.kubernetes.example_kubernetes_resource"]], "tests.system.providers.cncf.kubernetes.example_spark_kubernetes": [[50, "module-tests.system.providers.cncf.kubernetes.example_spark_kubernetes"]], "tests.system.providers.cncf.kubernetes": [[51, "module-tests.system.providers.cncf.kubernetes"]], "Changelog": [[52, "changelog"]], "8.1.1": [[52, "id1"], [54, "id1"]], "Bug Fixes": [[52, "bug-fixes"], [52, "id3"], [52, "id5"], [52, "id9"], [52, "id13"], [52, "id20"], [52, "id22"], [52, "id26"], [52, "id30"], [52, "id34"], [52, "id37"], [52, "id41"], [52, "id44"], [52, "id48"], [52, "id53"], [52, "id60"], [52, "id63"], [52, "id67"], [52, "id73"], [52, "id82"], [52, "id85"], [52, "id87"], [52, "id90"], [52, "id92"], [52, "id95"], [52, "id102"], [52, "id105"], [52, "id108"], [52, "id111"], [52, "id115"], [52, "id118"], [52, "id120"], [52, "id124"], [52, "id125"], [52, "id133"], [52, "id139"], [52, "id142"], [52, "id146"], [52, "id148"], [52, "id151"], [52, "id155"], [52, "id158"]], "8.1.0": [[52, "id2"], [54, "id2"]], "Features": [[52, "features"], [52, "id8"], [52, "id12"], [52, "id16"], [52, "id19"], [52, "id25"], [52, "id29"], [52, "id33"], [52, "id40"], [52, "id47"], [52, "id56"], [52, "id59"], [52, "id62"], [52, "id66"], [52, "id72"], [52, "id76"], [52, "id79"], [52, "id81"], [52, "id89"], [52, "id94"], [52, "id101"], [52, "id104"], [52, "id107"], [52, "id110"], [52, "id114"], [52, "id123"], [52, "id130"], [52, "id138"], [52, "id141"], [52, "id144"], [52, "id150"], [52, "id154"], [52, "id157"], [52, "id160"]], "Misc": [[52, "misc"], [52, "id6"], [52, "id10"], [52, "id14"], [52, "id17"], [52, "id23"], [52, "id27"], [52, "id31"], [52, "id38"], [52, "id42"], [52, "id45"], [52, "id49"], [52, "id51"], [52, "id54"], [52, "id57"], [52, "id64"], [52, "id68"], [52, "id74"], [52, "id83"], [52, "id96"], [52, "id100"], [52, "id112"], [52, "id116"], [52, "id126"], [52, "id128"], [52, "id131"], [52, "id135"]], "8.0.1": [[52, "id4"], [54, "id3"]], "8.0.0": [[52, "id7"], [54, "id4"]], "Breaking changes": [[52, "breaking-changes"], [52, "id71"], [52, "id78"], [52, "id99"], [52, "id122"], [52, "id137"], [52, "id153"]], "7.14.0": [[52, "id11"], [54, "id6"]], "7.13.0": [[52, "id15"], [54, "id7"]], "7.12.0": [[52, "id18"], [54, "id8"]], "7.11.0": [[52, "id21"], [54, "id9"]], "7.10.0": [[52, "id24"], [54, "id10"]], "7.9.0": [[52, "id28"], [54, "id11"]], "7.8.0": [[52, "id32"], [54, "id12"]], "7.7.0": [[52, "id35"], [54, "id13"]], "7.6.0": [[52, "id39"], [54, "id14"]], "7.5.1": [[52, "id43"], [54, "id15"]], "7.5.0": [[52, "id46"], [54, "id18"]], "7.4.2": [[52, "id50"], [54, "id19"]], "7.4.1": [[52, "id52"], [54, "id20"]], "7.4.0": [[52, "id55"], [54, "id21"]], "7.3.0": [[52, "id58"], [54, "id22"]], "7.2.0": [[52, "id61"], [54, "id23"]], "7.1.0": [[52, "id65"], [54, "id24"]], "7.0.0": [[52, "id69"], [54, "id25"]], "6.1.0": [[52, "id75"], [54, "id27"]], "6.0.0": [[52, "id77"], [54, "id28"]], "5.3.0": [[52, "id80"], [54, "id29"]], "5.2.2": [[52, "id84"], [54, "id30"]], "5.2.1": [[52, "id86"], [54, "id31"]], "5.2.0": [[52, "id88"], [54, "id32"]], "5.1.1": [[52, "id91"], [54, "id33"]], "5.1.0": [[52, "id93"], [54, "id34"]], "5.0.0": [[52, "id97"], [54, "id35"]], "New deprecations": [[52, "new-deprecations"]], "4.4.0": [[52, "id103"], [54, "id36"]], "4.3.0": [[52, "id106"], [54, "id37"]], "4.2.0": [[52, "id109"], [54, "id38"]], "4.1.0": [[52, "id113"], [54, "id39"]], "4.0.2": [[52, "id117"], [54, "id40"]], "4.0.1": [[52, "id119"], [54, "id41"]], "4.0.0": [[52, "id121"], [54, "id42"]], "3.1.2 (YANKED)": [[52, "yanked"]], "3.1.1 (YANKED)": [[52, "id127"]], "3.1.0 (YANKED)": [[52, "id129"]], "3.0.2 (YANKED)": [[52, "id132"]], "3.0.1 (YANKED)": [[52, "id134"]], "3.0.0": [[52, "id136"], [54, "id48"]], "Parameter is_delete_operator_pod has new default": [[52, "parameter-is-delete-operator-pod-has-new-default"]], "Notes on changes KubernetesPodOperator and PodLauncher": [[52, "notes-on-changes-kubernetespodoperator-and-podlauncher"]], "Overview": [[52, "overview"]], "Details on method renames, refactors, and deletions": [[52, "details-on-method-renames-refactors-and-deletions"]], "2.2.0": [[52, "id140"], [54, "id49"]], "2.1.0": [[52, "id143"], [54, "id50"]], "2.0.3": [[52, "id145"], [54, "id51"]], "2.0.2": [[52, "id147"], [54, "id52"]], "2.0.1": [[52, "id149"], [54, "id53"]], "2.0.0": [[52, "id152"], [54, "id54"]], "1.2.0": [[52, "id156"], [54, "id55"]], "1.1.0": [[52, "id159"], [54, "id56"]], "1.0.2": [[52, "id161"], [54, "id58"]], "Bug fixes": [[52, "id162"], [52, "id164"]], "1.0.1": [[52, "id163"], [54, "id59"]], "1.0.0": [[52, "id165"], [54, "id60"]], "Kubernetes Executor Commands": [[53, "kubernetes-executor-commands"]], "Positional Arguments": [[53, "positional-arguments"], [53, "positional-arguments_repeat1"], [53, "positional-arguments_repeat2"]], "Sub-commands": [[53, "Sub-commands"], [53, "Sub-commands_repeat1"]], "kubernetes": [[53, "kubernetes"]], "cleanup-pods": [[53, "cleanup-pods"]], "Named Arguments": [[53, "named-arguments"], [53, "named-arguments_repeat1"]], "generate-dag-yaml": [[53, "generate-dag-yaml"]], "Package apache-airflow-providers-cncf-kubernetes": [[54, "package-apache-airflow-providers-cncf-kubernetes"]], "3.1.2": [[54, "id43"]], "3.1.1": [[54, "id44"]], "3.1.0": [[54, "id45"]], "3.0.2": [[54, "id46"]], "3.0.1": [[54, "id47"]], "Configuration Reference": [[55, "configuration-reference"]], "Sections:": [[55, "sections"]], "[kubernetes_executor]": [[55, "kubernetes-executor"]], "api_client_retry_configuration": [[55, "api-client-retry-configuration"]], "cluster_context": [[55, "cluster-context"]], "config_file": [[55, "config-file"]], "delete_option_kwargs": [[55, "delete-option-kwargs"]], "delete_worker_pods": [[55, "delete-worker-pods"]], "delete_worker_pods_on_failure": [[55, "delete-worker-pods-on-failure"]], "enable_tcp_keepalive": [[55, "enable-tcp-keepalive"]], "in_cluster": [[55, "in-cluster"]], "kube_client_request_args": [[55, "kube-client-request-args"]], "logs_task_metadata": [[55, "logs-task-metadata"]], "multi_namespace_mode": [[55, "multi-namespace-mode"]], "multi_namespace_mode_namespace_list": [[55, "multi-namespace-mode-namespace-list"]], "namespace": [[55, "namespace"]], "pod_template_file": [[55, "pod-template-file"], [59, "pod-template-file"]], "ssl_ca_cert": [[55, "ssl-ca-cert"]], "task_publish_max_retries": [[55, "task-publish-max-retries"]], "tcp_keep_cnt": [[55, "tcp-keep-cnt"]], "tcp_keep_idle": [[55, "tcp-keep-idle"]], "tcp_keep_intvl": [[55, "tcp-keep-intvl"]], "verify_ssl": [[55, "verify-ssl"]], "worker_container_repository": [[55, "worker-container-repository"]], "worker_container_tag": [[55, "worker-container-tag"]], "worker_pod_pending_fatal_container_state_reasons": [[55, "worker-pod-pending-fatal-container-state-reasons"]], "worker_pods_creation_batch_size": [[55, "worker-pods-creation-batch-size"]], "worker_pods_queued_check_interval": [[55, "worker-pods-queued-check-interval"]], "worker_pods_pending_timeout (Deprecated)": [[55, "worker-pods-pending-timeout-deprecated"]], "worker_pods_pending_timeout_check_interval (Deprecated)": [[55, "worker-pods-pending-timeout-check-interval-deprecated"]], "[local_kubernetes_executor]": [[55, "local-kubernetes-executor"]], "kubernetes_queue": [[55, "kubernetes-queue"]], "Kubernetes cluster Connection": [[56, "kubernetes-cluster-connection"]], "Authenticating to Kubernetes cluster": [[56, "authenticating-to-kubernetes-cluster"]], "Default Connection IDs": [[56, "default-connection-ids"]], "Configuring the Connection": [[56, "configuring-the-connection"]], "apache-airflow-providers-cncf-kubernetes": [[57, "apache-airflow-providers-cncf-kubernetes"]], "apache-airflow-providers-cncf-kubernetes package": [[57, "apache-airflow-providers-cncf-kubernetes-package"]], "Provider package": [[57, "provider-package"]], "Installation": [[57, "installation"]], "Requirements": [[57, "requirements"]], "Installing from sources": [[58, "installing-from-sources"]], "Released packages": [[58, "released-packages"]], "Release integrity": [[58, "release-integrity"]], "Verifying PyPI releases": [[58, "verifying-pypi-releases"]], "Kubernetes Executor": [[59, "kubernetes-executor"]], "Configuration": [[59, "configuration"]], "Base image": [[59, "base-image"]], "Pod name": [[59, "pod-name"]], "Example pod templates": [[59, "example-pod-templates"]], "pod_override": [[59, "pod-override"]], "Managing DAGs and logs": [[59, "managing-dags-and-logs"]], "Comparison with CeleryExecutor": [[59, "comparison-with-celeryexecutor"]], "Fault Tolerance": [[59, "fault-tolerance"]], "Handling Worker Pod Crashes": [[59, "handling-worker-pod-crashes"]], "But What About Cases Where the Scheduler Pod Crashes?": [[59, "but-what-about-cases-where-the-scheduler-pod-crashes"]], "LocalKubernetes Executor": [[60, "localkubernetes-executor"]], "Table of Contents": [[61, "table-of-contents"]], "KubernetesPodOperator": [[61, "kubernetespodoperator"]], "How does this operator work?": [[61, "how-does-this-operator-work"], [61, "id1"], [61, "id3"]], "Debugging KubernetesPodOperator": [[61, "debugging-kubernetespodoperator"]], "Argument precedence": [[61, "argument-precedence"]], "How to use cluster ConfigMaps, Secrets, and Volumes with Pod?": [[61, "how-to-use-cluster-configmaps-secrets-and-volumes-with-pod"]], "Difference between KubernetesPodOperator and Kubernetes object spec": [[61, "difference-between-kubernetespodoperator-and-kubernetes-object-spec"]], "How to use private images (container registry)?": [[61, "how-to-use-private-images-container-registry"]], "How does XCom work?": [[61, "how-does-xcom-work"]], "Include error message in email alert": [[61, "include-error-message-in-email-alert"]], "KubernetesPodOperator callbacks": [[61, "kubernetespodoperator-callbacks"]], "Example:": [[61, "example"]], "Reference": [[61, "reference"], [61, "id2"]], "SparkKubernetesOperator": [[61, "sparkkubernetesoperator"]], "Usage examples": [[61, "usage-examples"]], "KubernetesJobOperator": [[61, "kubernetesjoboperator"]], "Difference between KubernetesPodOperator and KubernetesJobOperator": [[61, "difference-between-kubernetespodoperator-and-kubernetesjoboperator"]], "KubernetesDeleteJobOperator": [[61, "kubernetesdeletejoboperator"]], "KubernetesPatchJobOperator": [[61, "kubernetespatchjoboperator"]], "Releasing security patches": [[62, "releasing-security-patches"]]}, "indexentries": {"async (airflow.providers.cncf.kubernetes.callbacks.executionmode attribute)": [[0, "airflow.providers.cncf.kubernetes.callbacks.ExecutionMode.ASYNC"]], "executionmode (class in airflow.providers.cncf.kubernetes.callbacks)": [[0, "airflow.providers.cncf.kubernetes.callbacks.ExecutionMode"]], "kubernetespodoperatorcallback (class in airflow.providers.cncf.kubernetes.callbacks)": [[0, "airflow.providers.cncf.kubernetes.callbacks.KubernetesPodOperatorCallback"]], "sync (airflow.providers.cncf.kubernetes.callbacks.executionmode attribute)": [[0, "airflow.providers.cncf.kubernetes.callbacks.ExecutionMode.SYNC"]], "airflow.providers.cncf.kubernetes.callbacks": [[0, "module-airflow.providers.cncf.kubernetes.callbacks"]], "client_type (in module airflow.providers.cncf.kubernetes.callbacks)": [[0, "airflow.providers.cncf.kubernetes.callbacks.client_type"]], "module": [[0, "module-airflow.providers.cncf.kubernetes.callbacks"], [1, "module-airflow.providers.cncf.kubernetes.decorators"], [2, "module-airflow.providers.cncf.kubernetes.decorators.kubernetes"], [3, "module-airflow.providers.cncf.kubernetes.executors"], [4, "module-airflow.providers.cncf.kubernetes.executors.kubernetes_executor"], [5, "module-airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types"], [6, "module-airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils"], [7, "module-airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor"], [8, "module-airflow.providers.cncf.kubernetes.hooks"], [9, "module-airflow.providers.cncf.kubernetes.hooks.kubernetes"], [10, "module-airflow.providers.cncf.kubernetes"], [11, "module-airflow.providers.cncf.kubernetes.k8s_model"], [12, "module-airflow.providers.cncf.kubernetes.kube_client"], [13, "module-airflow.providers.cncf.kubernetes.kube_config"], [14, "module-airflow.providers.cncf.kubernetes.kubernetes_executor_templates"], [15, "module-airflow.providers.cncf.kubernetes.kubernetes_helper_functions"], [16, "module-airflow.providers.cncf.kubernetes.operators.custom_object_launcher"], [17, "module-airflow.providers.cncf.kubernetes.operators"], [18, "module-airflow.providers.cncf.kubernetes.operators.job"], [19, "module-airflow.providers.cncf.kubernetes.operators.kubernetes_pod"], [20, "module-airflow.providers.cncf.kubernetes.operators.pod"], [21, "module-airflow.providers.cncf.kubernetes.operators.resource"], [22, "module-airflow.providers.cncf.kubernetes.operators.spark_kubernetes"], [23, "module-airflow.providers.cncf.kubernetes.pod_generator"], [24, "module-airflow.providers.cncf.kubernetes.pod_generator_deprecated"], [25, "module-airflow.providers.cncf.kubernetes.pod_launcher_deprecated"], [26, "module-airflow.providers.cncf.kubernetes.pod_template_file_examples"], [27, "module-airflow.providers.cncf.kubernetes.python_kubernetes_script"], [28, "module-airflow.providers.cncf.kubernetes.resource_convert.configmap"], [29, "module-airflow.providers.cncf.kubernetes.resource_convert.env_variable"], [30, "module-airflow.providers.cncf.kubernetes.resource_convert"], [31, "module-airflow.providers.cncf.kubernetes.resource_convert.secret"], [32, "module-airflow.providers.cncf.kubernetes.secret"], [33, "module-airflow.providers.cncf.kubernetes.sensors"], [34, "module-airflow.providers.cncf.kubernetes.sensors.spark_kubernetes"], [35, "module-airflow.providers.cncf.kubernetes.template_rendering"], [36, "module-airflow.providers.cncf.kubernetes.triggers"], [37, "module-airflow.providers.cncf.kubernetes.triggers.job"], [38, "module-airflow.providers.cncf.kubernetes.triggers.kubernetes_pod"], [39, "module-airflow.providers.cncf.kubernetes.triggers.pod"], [40, "module-airflow.providers.cncf.kubernetes.utils.delete_from"], [41, "module-airflow.providers.cncf.kubernetes.utils"], [42, "module-airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator"], [43, "module-airflow.providers.cncf.kubernetes.utils.pod_manager"], [44, "module-airflow.providers.cncf.kubernetes.utils.xcom_sidecar"], [45, "module-tests.system.providers.cncf.kubernetes.example_kubernetes"], [46, "module-tests.system.providers.cncf.kubernetes.example_kubernetes_async"], [47, "module-tests.system.providers.cncf.kubernetes.example_kubernetes_decorator"], [48, "module-tests.system.providers.cncf.kubernetes.example_kubernetes_job"], [49, "module-tests.system.providers.cncf.kubernetes.example_kubernetes_resource"], [50, "module-tests.system.providers.cncf.kubernetes.example_spark_kubernetes"], [51, "module-tests.system.providers.cncf.kubernetes"]], "on_operator_resuming() (airflow.providers.cncf.kubernetes.callbacks.kubernetespodoperatorcallback static method)": [[0, "airflow.providers.cncf.kubernetes.callbacks.KubernetesPodOperatorCallback.on_operator_resuming"]], "on_pod_cleanup() (airflow.providers.cncf.kubernetes.callbacks.kubernetespodoperatorcallback static method)": [[0, "airflow.providers.cncf.kubernetes.callbacks.KubernetesPodOperatorCallback.on_pod_cleanup"]], "on_pod_completion() (airflow.providers.cncf.kubernetes.callbacks.kubernetespodoperatorcallback static method)": [[0, "airflow.providers.cncf.kubernetes.callbacks.KubernetesPodOperatorCallback.on_pod_completion"]], "on_pod_creation() (airflow.providers.cncf.kubernetes.callbacks.kubernetespodoperatorcallback static method)": [[0, "airflow.providers.cncf.kubernetes.callbacks.KubernetesPodOperatorCallback.on_pod_creation"]], "on_pod_starting() (airflow.providers.cncf.kubernetes.callbacks.kubernetespodoperatorcallback static method)": [[0, "airflow.providers.cncf.kubernetes.callbacks.KubernetesPodOperatorCallback.on_pod_starting"]], "on_sync_client_creation() (airflow.providers.cncf.kubernetes.callbacks.kubernetespodoperatorcallback static method)": [[0, "airflow.providers.cncf.kubernetes.callbacks.KubernetesPodOperatorCallback.on_sync_client_creation"]], "progress_callback() (airflow.providers.cncf.kubernetes.callbacks.kubernetespodoperatorcallback static method)": [[0, "airflow.providers.cncf.kubernetes.callbacks.KubernetesPodOperatorCallback.progress_callback"]], "airflow.providers.cncf.kubernetes.decorators": [[1, "module-airflow.providers.cncf.kubernetes.decorators"]], "airflow.providers.cncf.kubernetes.decorators.kubernetes": [[2, "module-airflow.providers.cncf.kubernetes.decorators.kubernetes"]], "kubernetes_task() (in module airflow.providers.cncf.kubernetes.decorators.kubernetes)": [[2, "airflow.providers.cncf.kubernetes.decorators.kubernetes.kubernetes_task"]], "airflow.providers.cncf.kubernetes.executors": [[3, "module-airflow.providers.cncf.kubernetes.executors"]], "arg_min_pending_minutes (in module airflow.providers.cncf.kubernetes.executors.kubernetes_executor)": [[4, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.ARG_MIN_PENDING_MINUTES"]], "arg_namespace (in module airflow.providers.cncf.kubernetes.executors.kubernetes_executor)": [[4, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.ARG_NAMESPACE"]], "kubernetes_commands (in module airflow.providers.cncf.kubernetes.executors.kubernetes_executor)": [[4, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KUBERNETES_COMMANDS"]], "kubernetesexecutor (class in airflow.providers.cncf.kubernetes.executors.kubernetes_executor)": [[4, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KubernetesExecutor"]], "running_pod_log_lines (airflow.providers.cncf.kubernetes.executors.kubernetes_executor.kubernetesexecutor attribute)": [[4, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KubernetesExecutor.RUNNING_POD_LOG_LINES"]], "adopt_launched_task() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor.kubernetesexecutor method)": [[4, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KubernetesExecutor.adopt_launched_task"]], "airflow.providers.cncf.kubernetes.executors.kubernetes_executor": [[4, "module-airflow.providers.cncf.kubernetes.executors.kubernetes_executor"]], "base_version (in module airflow.providers.cncf.kubernetes.executors.kubernetes_executor)": [[4, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.base_version"]], "cleanup_stuck_queued_tasks() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor.kubernetesexecutor method)": [[4, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KubernetesExecutor.cleanup_stuck_queued_tasks"]], "clear_not_launched_queued_tasks() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor.kubernetesexecutor method)": [[4, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KubernetesExecutor.clear_not_launched_queued_tasks"]], "end() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor.kubernetesexecutor method)": [[4, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KubernetesExecutor.end"]], "execute_async() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor.kubernetesexecutor method)": [[4, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KubernetesExecutor.execute_async"]], "get_cli_commands() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor.kubernetesexecutor static method)": [[4, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KubernetesExecutor.get_cli_commands"]], "get_task_log() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor.kubernetesexecutor method)": [[4, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KubernetesExecutor.get_task_log"]], "start() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor.kubernetesexecutor method)": [[4, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KubernetesExecutor.start"]], "supports_ad_hoc_ti_run (airflow.providers.cncf.kubernetes.executors.kubernetes_executor.kubernetesexecutor attribute)": [[4, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KubernetesExecutor.supports_ad_hoc_ti_run"]], "sync() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor.kubernetesexecutor method)": [[4, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KubernetesExecutor.sync"]], "terminate() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor.kubernetesexecutor method)": [[4, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KubernetesExecutor.terminate"]], "try_adopt_task_instances() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor.kubernetesexecutor method)": [[4, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor.KubernetesExecutor.try_adopt_task_instances"]], "adopted (in module airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types)": [[5, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types.ADOPTED"]], "all_namespaces (in module airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types)": [[5, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types.ALL_NAMESPACES"]], "kubernetesjobtype (in module airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types)": [[5, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types.KubernetesJobType"]], "pod_executor_done_key (in module airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types)": [[5, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types.POD_EXECUTOR_DONE_KEY"]], "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types": [[5, "module-airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types"]], "airflowkubernetesscheduler (class in airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils)": [[6, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.AirflowKubernetesScheduler"]], "kubernetesjobwatcher (class in airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils)": [[6, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.KubernetesJobWatcher"]], "resourceversion (class in airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils)": [[6, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.ResourceVersion"]], "singleton (class in airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils)": [[6, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.Singleton"]], "t (in module airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils)": [[6, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.T"]], "__call__() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.singleton method)": [[6, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.Singleton.__call__"]], "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils": [[6, "module-airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils"]], "delete_pod() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.airflowkubernetesscheduler method)": [[6, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.AirflowKubernetesScheduler.delete_pod"]], "get_base_pod_from_template() (in module airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils)": [[6, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.get_base_pod_from_template"]], "patch_pod_executor_done() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.airflowkubernetesscheduler method)": [[6, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.AirflowKubernetesScheduler.patch_pod_executor_done"]], "process_error() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.kubernetesjobwatcher method)": [[6, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.KubernetesJobWatcher.process_error"]], "process_status() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.kubernetesjobwatcher method)": [[6, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.KubernetesJobWatcher.process_status"]], "process_watcher_task() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.airflowkubernetesscheduler method)": [[6, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.AirflowKubernetesScheduler.process_watcher_task"]], "resource_version (airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.resourceversion attribute)": [[6, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.ResourceVersion.resource_version"]], "run() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.kubernetesjobwatcher method)": [[6, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.KubernetesJobWatcher.run"]], "run_next() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.airflowkubernetesscheduler method)": [[6, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.AirflowKubernetesScheduler.run_next"]], "run_pod_async() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.airflowkubernetesscheduler method)": [[6, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.AirflowKubernetesScheduler.run_pod_async"]], "sync() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.airflowkubernetesscheduler method)": [[6, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.AirflowKubernetesScheduler.sync"]], "terminate() (airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.airflowkubernetesscheduler method)": [[6, "airflow.providers.cncf.kubernetes.executors.kubernetes_executor_utils.AirflowKubernetesScheduler.terminate"]], "kubernetes_queue (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor attribute)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.KUBERNETES_QUEUE"]], "localkubernetesexecutor (class in airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor"]], "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor": [[7, "module-airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor"]], "callback_sink (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor attribute)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.callback_sink"]], "change_sensor_mode_to_reschedule (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor attribute)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.change_sensor_mode_to_reschedule"]], "cleanup_stuck_queued_tasks() (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor method)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.cleanup_stuck_queued_tasks"]], "debug_dump() (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor method)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.debug_dump"]], "end() (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor method)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.end"]], "get_cli_commands() (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor static method)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.get_cli_commands"]], "get_event_buffer() (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor method)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.get_event_buffer"]], "get_task_log() (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor method)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.get_task_log"]], "has_task() (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor method)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.has_task"]], "heartbeat() (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor method)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.heartbeat"]], "is_local (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor attribute)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.is_local"]], "is_production (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor attribute)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.is_production"]], "is_single_threaded (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor attribute)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.is_single_threaded"]], "job_id (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor property)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.job_id"]], "queue_command() (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor method)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.queue_command"]], "queue_task_instance() (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor method)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.queue_task_instance"]], "queued_tasks (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor property)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.queued_tasks"]], "running (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor property)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.running"]], "send_callback() (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor method)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.send_callback"]], "serve_logs (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor attribute)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.serve_logs"]], "slots_available (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor property)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.slots_available"]], "start() (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor method)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.start"]], "supports_ad_hoc_ti_run (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor attribute)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.supports_ad_hoc_ti_run"]], "supports_pickling (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor attribute)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.supports_pickling"]], "supports_sentry (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor attribute)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.supports_sentry"]], "terminate() (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor method)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.terminate"]], "try_adopt_task_instances() (airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.localkubernetesexecutor method)": [[7, "airflow.providers.cncf.kubernetes.executors.local_kubernetes_executor.LocalKubernetesExecutor.try_adopt_task_instances"]], "airflow.providers.cncf.kubernetes.hooks": [[8, "module-airflow.providers.cncf.kubernetes.hooks"]], "asynckuberneteshook (class in airflow.providers.cncf.kubernetes.hooks.kubernetes)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.AsyncKubernetesHook"]], "default_namespace (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook attribute)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.DEFAULT_NAMESPACE"]], "job_final_status_condition_types (in module airflow.providers.cncf.kubernetes.hooks.kubernetes)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.JOB_FINAL_STATUS_CONDITION_TYPES"]], "job_status_condition_types (in module airflow.providers.cncf.kubernetes.hooks.kubernetes)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.JOB_STATUS_CONDITION_TYPES"]], "kuberneteshook (class in airflow.providers.cncf.kubernetes.hooks.kubernetes)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook"]], "loading_kube_config_file_resource (in module airflow.providers.cncf.kubernetes.hooks.kubernetes)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.LOADING_KUBE_CONFIG_FILE_RESOURCE"]], "airflow.providers.cncf.kubernetes.hooks.kubernetes": [[9, "module-airflow.providers.cncf.kubernetes.hooks.kubernetes"]], "api_client() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.api_client"]], "apps_v1_client() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.apps_v1_client"]], "batch_v1_client() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.batch_v1_client"]], "conn_extras() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.conn_extras"]], "conn_name_attr (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook attribute)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.conn_name_attr"]], "conn_type (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook attribute)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.conn_type"]], "core_v1_client() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.core_v1_client"]], "create_custom_object() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.create_custom_object"]], "create_job() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.create_job"]], "custom_object_client() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.custom_object_client"]], "default_conn_name (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook attribute)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.default_conn_name"]], "delete_custom_object() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.delete_custom_object"]], "delete_pod() (airflow.providers.cncf.kubernetes.hooks.kubernetes.asynckuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.AsyncKubernetesHook.delete_pod"]], "get_conn() (airflow.providers.cncf.kubernetes.hooks.kubernetes.asynckuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.AsyncKubernetesHook.get_conn"]], "get_conn() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.get_conn"]], "get_conn_extras() (airflow.providers.cncf.kubernetes.hooks.kubernetes.asynckuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.AsyncKubernetesHook.get_conn_extras"]], "get_connection() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook class method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.get_connection"]], "get_connection_form_widgets() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook class method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.get_connection_form_widgets"]], "get_custom_object() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.get_custom_object"]], "get_deployment_status() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.get_deployment_status"]], "get_job() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.get_job"]], "get_job_status() (airflow.providers.cncf.kubernetes.hooks.kubernetes.asynckuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.AsyncKubernetesHook.get_job_status"]], "get_job_status() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.get_job_status"]], "get_namespace() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.get_namespace"]], "get_namespaced_pod_list() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.get_namespaced_pod_list"]], "get_pod() (airflow.providers.cncf.kubernetes.hooks.kubernetes.asynckuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.AsyncKubernetesHook.get_pod"]], "get_pod() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.get_pod"]], "get_pod_log_stream() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.get_pod_log_stream"]], "get_pod_logs() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.get_pod_logs"]], "get_ui_field_behaviour() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook class method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.get_ui_field_behaviour"]], "get_xcom_sidecar_container_image() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.get_xcom_sidecar_container_image"]], "get_xcom_sidecar_container_resources() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.get_xcom_sidecar_container_resources"]], "hook_name (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook attribute)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.hook_name"]], "is_in_cluster (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook property)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.is_in_cluster"]], "is_job_complete() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.is_job_complete"]], "is_job_failed() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook static method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.is_job_failed"]], "is_job_successful() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook static method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.is_job_successful"]], "list_jobs_all_namespaces() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.list_jobs_all_namespaces"]], "list_jobs_from_namespace() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.list_jobs_from_namespace"]], "patch_namespaced_job() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.patch_namespaced_job"]], "read_logs() (airflow.providers.cncf.kubernetes.hooks.kubernetes.asynckuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.AsyncKubernetesHook.read_logs"]], "wait_until_job_complete() (airflow.providers.cncf.kubernetes.hooks.kubernetes.asynckuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.AsyncKubernetesHook.wait_until_job_complete"]], "wait_until_job_complete() (airflow.providers.cncf.kubernetes.hooks.kubernetes.kuberneteshook method)": [[9, "airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook.wait_until_job_complete"]], "__version__ (in module airflow.providers.cncf.kubernetes)": [[10, "airflow.providers.cncf.kubernetes.__version__"]], "airflow.providers.cncf.kubernetes": [[10, "module-airflow.providers.cncf.kubernetes"]], "k8smodel (class in airflow.providers.cncf.kubernetes.k8s_model)": [[11, "airflow.providers.cncf.kubernetes.k8s_model.K8SModel"]], "airflow.providers.cncf.kubernetes.k8s_model": [[11, "module-airflow.providers.cncf.kubernetes.k8s_model"]], "append_to_pod() (in module airflow.providers.cncf.kubernetes.k8s_model)": [[11, "airflow.providers.cncf.kubernetes.k8s_model.append_to_pod"]], "attach_to_pod() (airflow.providers.cncf.kubernetes.k8s_model.k8smodel method)": [[11, "airflow.providers.cncf.kubernetes.k8s_model.K8SModel.attach_to_pod"]], "airflow.providers.cncf.kubernetes.kube_client": [[12, "module-airflow.providers.cncf.kubernetes.kube_client"]], "get_kube_client() (in module airflow.providers.cncf.kubernetes.kube_client)": [[12, "airflow.providers.cncf.kubernetes.kube_client.get_kube_client"]], "has_kubernetes (in module airflow.providers.cncf.kubernetes.kube_client)": [[12, "airflow.providers.cncf.kubernetes.kube_client.has_kubernetes"]], "log (in module airflow.providers.cncf.kubernetes.kube_client)": [[12, "airflow.providers.cncf.kubernetes.kube_client.log"]], "kubeconfig (class in airflow.providers.cncf.kubernetes.kube_config)": [[13, "airflow.providers.cncf.kubernetes.kube_config.KubeConfig"]], "airflow.providers.cncf.kubernetes.kube_config": [[13, "module-airflow.providers.cncf.kubernetes.kube_config"]], "core_section (airflow.providers.cncf.kubernetes.kube_config.kubeconfig attribute)": [[13, "airflow.providers.cncf.kubernetes.kube_config.KubeConfig.core_section"]], "kubernetes_section (airflow.providers.cncf.kubernetes.kube_config.kubeconfig attribute)": [[13, "airflow.providers.cncf.kubernetes.kube_config.KubeConfig.kubernetes_section"]], "logging_section (airflow.providers.cncf.kubernetes.kube_config.kubeconfig attribute)": [[13, "airflow.providers.cncf.kubernetes.kube_config.KubeConfig.logging_section"]], "airflow.providers.cncf.kubernetes.kubernetes_executor_templates": [[14, "module-airflow.providers.cncf.kubernetes.kubernetes_executor_templates"]], "pod_name_max_length (in module airflow.providers.cncf.kubernetes.kubernetes_helper_functions)": [[15, "airflow.providers.cncf.kubernetes.kubernetes_helper_functions.POD_NAME_MAX_LENGTH"]], "airflow.providers.cncf.kubernetes.kubernetes_helper_functions": [[15, "module-airflow.providers.cncf.kubernetes.kubernetes_helper_functions"]], "alphanum_lower (in module airflow.providers.cncf.kubernetes.kubernetes_helper_functions)": [[15, "airflow.providers.cncf.kubernetes.kubernetes_helper_functions.alphanum_lower"]], "annotations_for_logging_task_metadata() (in module airflow.providers.cncf.kubernetes.kubernetes_helper_functions)": [[15, "airflow.providers.cncf.kubernetes.kubernetes_helper_functions.annotations_for_logging_task_metadata"]], "annotations_to_key() (in module airflow.providers.cncf.kubernetes.kubernetes_helper_functions)": [[15, "airflow.providers.cncf.kubernetes.kubernetes_helper_functions.annotations_to_key"]], "create_pod_id() (in module airflow.providers.cncf.kubernetes.kubernetes_helper_functions)": [[15, "airflow.providers.cncf.kubernetes.kubernetes_helper_functions.create_pod_id"]], "create_unique_id() (in module airflow.providers.cncf.kubernetes.kubernetes_helper_functions)": [[15, "airflow.providers.cncf.kubernetes.kubernetes_helper_functions.create_unique_id"]], "get_logs_task_metadata() (in module airflow.providers.cncf.kubernetes.kubernetes_helper_functions)": [[15, "airflow.providers.cncf.kubernetes.kubernetes_helper_functions.get_logs_task_metadata"]], "log (in module airflow.providers.cncf.kubernetes.kubernetes_helper_functions)": [[15, "airflow.providers.cncf.kubernetes.kubernetes_helper_functions.log"]], "customobjectlauncher (class in airflow.providers.cncf.kubernetes.operators.custom_object_launcher)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.CustomObjectLauncher"]], "customobjectstatus (class in airflow.providers.cncf.kubernetes.operators.custom_object_launcher)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.CustomObjectStatus"]], "failed (airflow.providers.cncf.kubernetes.operators.custom_object_launcher.customobjectstatus attribute)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.CustomObjectStatus.FAILED"]], "kubernetesspec (class in airflow.providers.cncf.kubernetes.operators.custom_object_launcher)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.KubernetesSpec"]], "running (airflow.providers.cncf.kubernetes.operators.custom_object_launcher.customobjectstatus attribute)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.CustomObjectStatus.RUNNING"]], "submitted (airflow.providers.cncf.kubernetes.operators.custom_object_launcher.customobjectstatus attribute)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.CustomObjectStatus.SUBMITTED"]], "succeeded (airflow.providers.cncf.kubernetes.operators.custom_object_launcher.customobjectstatus attribute)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.CustomObjectStatus.SUCCEEDED"]], "sparkjobspec (class in airflow.providers.cncf.kubernetes.operators.custom_object_launcher)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.SparkJobSpec"]], "sparkresources (class in airflow.providers.cncf.kubernetes.operators.custom_object_launcher)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.SparkResources"]], "airflow.providers.cncf.kubernetes.operators.custom_object_launcher": [[16, "module-airflow.providers.cncf.kubernetes.operators.custom_object_launcher"]], "check_pod_start_failure() (airflow.providers.cncf.kubernetes.operators.custom_object_launcher.customobjectlauncher method)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.CustomObjectLauncher.check_pod_start_failure"]], "convert_resources() (airflow.providers.cncf.kubernetes.operators.custom_object_launcher.sparkresources method)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.SparkResources.convert_resources"]], "delete_spark_job() (airflow.providers.cncf.kubernetes.operators.custom_object_launcher.customobjectlauncher method)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.CustomObjectLauncher.delete_spark_job"]], "driver_resources (airflow.providers.cncf.kubernetes.operators.custom_object_launcher.sparkresources property)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.SparkResources.driver_resources"]], "executor_resources (airflow.providers.cncf.kubernetes.operators.custom_object_launcher.sparkresources property)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.SparkResources.executor_resources"]], "get_body() (airflow.providers.cncf.kubernetes.operators.custom_object_launcher.customobjectlauncher method)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.CustomObjectLauncher.get_body"]], "pod_manager() (airflow.providers.cncf.kubernetes.operators.custom_object_launcher.customobjectlauncher method)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.CustomObjectLauncher.pod_manager"]], "resources (airflow.providers.cncf.kubernetes.operators.custom_object_launcher.sparkresources property)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.SparkResources.resources"]], "set_attribute() (airflow.providers.cncf.kubernetes.operators.custom_object_launcher.kubernetesspec method)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.KubernetesSpec.set_attribute"]], "should_retry_start_spark_job() (in module airflow.providers.cncf.kubernetes.operators.custom_object_launcher)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.should_retry_start_spark_job"]], "spark_job_not_running() (airflow.providers.cncf.kubernetes.operators.custom_object_launcher.customobjectlauncher method)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.CustomObjectLauncher.spark_job_not_running"]], "start_spark_job() (airflow.providers.cncf.kubernetes.operators.custom_object_launcher.customobjectlauncher method)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.CustomObjectLauncher.start_spark_job"]], "update_resources() (airflow.providers.cncf.kubernetes.operators.custom_object_launcher.sparkjobspec method)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.SparkJobSpec.update_resources"]], "validate() (airflow.providers.cncf.kubernetes.operators.custom_object_launcher.sparkjobspec method)": [[16, "airflow.providers.cncf.kubernetes.operators.custom_object_launcher.SparkJobSpec.validate"]], "airflow.providers.cncf.kubernetes.operators": [[17, "module-airflow.providers.cncf.kubernetes.operators"]], "kubernetesdeletejoboperator (class in airflow.providers.cncf.kubernetes.operators.job)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesDeleteJobOperator"]], "kubernetesjoboperator (class in airflow.providers.cncf.kubernetes.operators.job)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator"]], "kubernetespatchjoboperator (class in airflow.providers.cncf.kubernetes.operators.job)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesPatchJobOperator"]], "airflow.providers.cncf.kubernetes.operators.job": [[18, "module-airflow.providers.cncf.kubernetes.operators.job"]], "build_job_request_obj() (airflow.providers.cncf.kubernetes.operators.job.kubernetesjoboperator method)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator.build_job_request_obj"]], "client() (airflow.providers.cncf.kubernetes.operators.job.kubernetesdeletejoboperator method)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesDeleteJobOperator.client"]], "client() (airflow.providers.cncf.kubernetes.operators.job.kubernetesjoboperator method)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator.client"]], "create_job() (airflow.providers.cncf.kubernetes.operators.job.kubernetesjoboperator method)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator.create_job"]], "deserialize_job_template_file() (airflow.providers.cncf.kubernetes.operators.job.kubernetesjoboperator static method)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator.deserialize_job_template_file"]], "execute() (airflow.providers.cncf.kubernetes.operators.job.kubernetesdeletejoboperator method)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesDeleteJobOperator.execute"]], "execute() (airflow.providers.cncf.kubernetes.operators.job.kubernetesjoboperator method)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator.execute"]], "execute() (airflow.providers.cncf.kubernetes.operators.job.kubernetespatchjoboperator method)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesPatchJobOperator.execute"]], "execute_complete() (airflow.providers.cncf.kubernetes.operators.job.kubernetesjoboperator method)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator.execute_complete"]], "execute_deferrable() (airflow.providers.cncf.kubernetes.operators.job.kubernetesjoboperator method)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator.execute_deferrable"]], "hook() (airflow.providers.cncf.kubernetes.operators.job.kubernetesdeletejoboperator method)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesDeleteJobOperator.hook"]], "hook() (airflow.providers.cncf.kubernetes.operators.job.kubernetesjoboperator method)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator.hook"]], "hook() (airflow.providers.cncf.kubernetes.operators.job.kubernetespatchjoboperator method)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesPatchJobOperator.hook"]], "log (in module airflow.providers.cncf.kubernetes.operators.job)": [[18, "airflow.providers.cncf.kubernetes.operators.job.log"]], "on_kill() (airflow.providers.cncf.kubernetes.operators.job.kubernetesjoboperator method)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator.on_kill"]], "reconcile_job_specs() (airflow.providers.cncf.kubernetes.operators.job.kubernetesjoboperator static method)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator.reconcile_job_specs"]], "reconcile_jobs() (airflow.providers.cncf.kubernetes.operators.job.kubernetesjoboperator static method)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator.reconcile_jobs"]], "template_fields (airflow.providers.cncf.kubernetes.operators.job.kubernetesdeletejoboperator attribute)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesDeleteJobOperator.template_fields"]], "template_fields (airflow.providers.cncf.kubernetes.operators.job.kubernetesjoboperator attribute)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesJobOperator.template_fields"]], "template_fields (airflow.providers.cncf.kubernetes.operators.job.kubernetespatchjoboperator attribute)": [[18, "airflow.providers.cncf.kubernetes.operators.job.KubernetesPatchJobOperator.template_fields"]], "airflow.providers.cncf.kubernetes.operators.kubernetes_pod": [[19, "module-airflow.providers.cncf.kubernetes.operators.kubernetes_pod"]], "base_container_name (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator attribute)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.BASE_CONTAINER_NAME"]], "istio_container_name (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator attribute)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.ISTIO_CONTAINER_NAME"]], "kill_istio_proxy_success_msg (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator attribute)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.KILL_ISTIO_PROXY_SUCCESS_MSG"]], "kube_config_env_var (in module airflow.providers.cncf.kubernetes.operators.pod)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KUBE_CONFIG_ENV_VAR"]], "kubernetespodoperator (class in airflow.providers.cncf.kubernetes.operators.pod)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator"]], "normal (airflow.providers.cncf.kubernetes.operators.pod.podeventtype attribute)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.PodEventType.NORMAL"]], "pod_checked_key (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator attribute)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.POD_CHECKED_KEY"]], "post_termination_timeout (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator attribute)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.POST_TERMINATION_TIMEOUT"]], "podeventtype (class in airflow.providers.cncf.kubernetes.operators.pod)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.PodEventType"]], "podreattachfailure": [[20, "airflow.providers.cncf.kubernetes.operators.pod.PodReattachFailure"]], "warning (airflow.providers.cncf.kubernetes.operators.pod.podeventtype attribute)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.PodEventType.WARNING"]], "airflow.providers.cncf.kubernetes.operators.pod": [[20, "module-airflow.providers.cncf.kubernetes.operators.pod"]], "alphanum_lower (in module airflow.providers.cncf.kubernetes.operators.pod)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.alphanum_lower"]], "await_pod_start() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.await_pod_start"]], "build_pod_request_obj() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.build_pod_request_obj"]], "cleanup() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.cleanup"]], "client() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.client"]], "dry_run() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.dry_run"]], "execute() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.execute"]], "execute_async() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.execute_async"]], "execute_complete() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.execute_complete"]], "execute_sync() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.execute_sync"]], "extract_xcom() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.extract_xcom"]], "find_pod() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.find_pod"]], "get_or_create_pod() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.get_or_create_pod"]], "hook() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.hook"]], "invoke_defer_method() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.invoke_defer_method"]], "is_istio_enabled() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.is_istio_enabled"]], "kill_istio_sidecar() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.kill_istio_sidecar"]], "on_kill() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.on_kill"]], "patch_already_checked() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.patch_already_checked"]], "pod_manager() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.pod_manager"]], "post_complete_action() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.post_complete_action"]], "process_pod_deletion() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.process_pod_deletion"]], "template_fields (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator attribute)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.template_fields"]], "template_fields_renderers (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator attribute)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.template_fields_renderers"]], "trigger_reentry() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.trigger_reentry"]], "write_logs() (airflow.providers.cncf.kubernetes.operators.pod.kubernetespodoperator method)": [[20, "airflow.providers.cncf.kubernetes.operators.pod.KubernetesPodOperator.write_logs"]], "kubernetescreateresourceoperator (class in airflow.providers.cncf.kubernetes.operators.resource)": [[21, "airflow.providers.cncf.kubernetes.operators.resource.KubernetesCreateResourceOperator"]], "kubernetesdeleteresourceoperator (class in airflow.providers.cncf.kubernetes.operators.resource)": [[21, "airflow.providers.cncf.kubernetes.operators.resource.KubernetesDeleteResourceOperator"]], "airflow.providers.cncf.kubernetes.operators.resource": [[21, "module-airflow.providers.cncf.kubernetes.operators.resource"]], "create_custom_from_yaml_object() (airflow.providers.cncf.kubernetes.operators.resource.kubernetescreateresourceoperator method)": [[21, "airflow.providers.cncf.kubernetes.operators.resource.KubernetesCreateResourceOperator.create_custom_from_yaml_object"]], "delete_custom_from_yaml_object() (airflow.providers.cncf.kubernetes.operators.resource.kubernetesdeleteresourceoperator method)": [[21, "airflow.providers.cncf.kubernetes.operators.resource.KubernetesDeleteResourceOperator.delete_custom_from_yaml_object"]], "execute() (airflow.providers.cncf.kubernetes.operators.resource.kubernetescreateresourceoperator method)": [[21, "airflow.providers.cncf.kubernetes.operators.resource.KubernetesCreateResourceOperator.execute"]], "execute() (airflow.providers.cncf.kubernetes.operators.resource.kubernetesdeleteresourceoperator method)": [[21, "airflow.providers.cncf.kubernetes.operators.resource.KubernetesDeleteResourceOperator.execute"]], "base_container_name (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator attribute)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.BASE_CONTAINER_NAME"]], "sparkkubernetesoperator (class in airflow.providers.cncf.kubernetes.operators.spark_kubernetes)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator"]], "airflow.providers.cncf.kubernetes.operators.spark_kubernetes": [[22, "module-airflow.providers.cncf.kubernetes.operators.spark_kubernetes"]], "client() (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator method)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.client"]], "create_job_name() (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator method)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.create_job_name"]], "create_labels_for_pod() (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator static method)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.create_labels_for_pod"]], "custom_obj_api() (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator method)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.custom_obj_api"]], "dry_run() (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator method)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.dry_run"]], "execute() (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator method)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.execute"]], "find_spark_job() (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator method)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.find_spark_job"]], "get_or_create_spark_crd() (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator method)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.get_or_create_spark_crd"]], "hook() (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator method)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.hook"]], "manage_template_specs() (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator method)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.manage_template_specs"]], "on_kill() (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator method)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.on_kill"]], "patch_already_checked() (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator method)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.patch_already_checked"]], "pod_manager() (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator method)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.pod_manager"]], "process_pod_deletion() (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator method)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.process_pod_deletion"]], "template_body (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator property)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.template_body"]], "template_ext (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator attribute)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.template_ext"]], "template_fields (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator attribute)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.template_fields"]], "template_fields_renderers (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator attribute)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.template_fields_renderers"]], "ui_color (airflow.providers.cncf.kubernetes.operators.spark_kubernetes.sparkkubernetesoperator attribute)": [[22, "airflow.providers.cncf.kubernetes.operators.spark_kubernetes.SparkKubernetesOperator.ui_color"]], "max_label_len (in module airflow.providers.cncf.kubernetes.pod_generator)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.MAX_LABEL_LEN"]], "podgenerator (class in airflow.providers.cncf.kubernetes.pod_generator)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.PodGenerator"]], "podmutationhookexception": [[23, "airflow.providers.cncf.kubernetes.pod_generator.PodMutationHookException"]], "podreconciliationerror": [[23, "airflow.providers.cncf.kubernetes.pod_generator.PodReconciliationError"]], "add_xcom_sidecar() (airflow.providers.cncf.kubernetes.pod_generator.podgenerator static method)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.PodGenerator.add_xcom_sidecar"]], "airflow.providers.cncf.kubernetes.pod_generator": [[23, "module-airflow.providers.cncf.kubernetes.pod_generator"]], "construct_pod() (airflow.providers.cncf.kubernetes.pod_generator.podgenerator class method)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.PodGenerator.construct_pod"]], "datetime_to_label_safe_datestring() (in module airflow.providers.cncf.kubernetes.pod_generator)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.datetime_to_label_safe_datestring"]], "deserialize_model_dict() (airflow.providers.cncf.kubernetes.pod_generator.podgenerator static method)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.PodGenerator.deserialize_model_dict"]], "deserialize_model_file() (airflow.providers.cncf.kubernetes.pod_generator.podgenerator static method)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.PodGenerator.deserialize_model_file"]], "extend_object_field() (in module airflow.providers.cncf.kubernetes.pod_generator)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.extend_object_field"]], "from_legacy_obj() (airflow.providers.cncf.kubernetes.pod_generator.podgenerator static method)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.PodGenerator.from_legacy_obj"]], "from_obj() (airflow.providers.cncf.kubernetes.pod_generator.podgenerator static method)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.PodGenerator.from_obj"]], "gen_pod() (airflow.providers.cncf.kubernetes.pod_generator.podgenerator method)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.PodGenerator.gen_pod"]], "label_safe_datestring_to_datetime() (in module airflow.providers.cncf.kubernetes.pod_generator)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.label_safe_datestring_to_datetime"]], "log (in module airflow.providers.cncf.kubernetes.pod_generator)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.log"]], "make_safe_label_value() (in module airflow.providers.cncf.kubernetes.pod_generator)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.make_safe_label_value"]], "make_unique_pod_id() (airflow.providers.cncf.kubernetes.pod_generator.podgenerator static method)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.PodGenerator.make_unique_pod_id"]], "merge_objects() (in module airflow.providers.cncf.kubernetes.pod_generator)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.merge_objects"]], "reconcile_containers() (airflow.providers.cncf.kubernetes.pod_generator.podgenerator static method)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.PodGenerator.reconcile_containers"]], "reconcile_metadata() (airflow.providers.cncf.kubernetes.pod_generator.podgenerator static method)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.PodGenerator.reconcile_metadata"]], "reconcile_pods() (airflow.providers.cncf.kubernetes.pod_generator.podgenerator static method)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.PodGenerator.reconcile_pods"]], "reconcile_specs() (airflow.providers.cncf.kubernetes.pod_generator.podgenerator static method)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.PodGenerator.reconcile_specs"]], "serialize_pod() (airflow.providers.cncf.kubernetes.pod_generator.podgenerator static method)": [[23, "airflow.providers.cncf.kubernetes.pod_generator.PodGenerator.serialize_pod"]], "max_label_len (in module airflow.providers.cncf.kubernetes.pod_generator_deprecated)": [[24, "airflow.providers.cncf.kubernetes.pod_generator_deprecated.MAX_LABEL_LEN"]], "max_pod_id_len (in module airflow.providers.cncf.kubernetes.pod_generator_deprecated)": [[24, "airflow.providers.cncf.kubernetes.pod_generator_deprecated.MAX_POD_ID_LEN"]], "poddefaults (class in airflow.providers.cncf.kubernetes.pod_generator_deprecated)": [[24, "airflow.providers.cncf.kubernetes.pod_generator_deprecated.PodDefaults"]], "podgenerator (class in airflow.providers.cncf.kubernetes.pod_generator_deprecated)": [[24, "airflow.providers.cncf.kubernetes.pod_generator_deprecated.PodGenerator"]], "sidecar_container (airflow.providers.cncf.kubernetes.pod_generator_deprecated.poddefaults attribute)": [[24, "airflow.providers.cncf.kubernetes.pod_generator_deprecated.PodDefaults.SIDECAR_CONTAINER"]], "sidecar_container_name (airflow.providers.cncf.kubernetes.pod_generator_deprecated.poddefaults attribute)": [[24, "airflow.providers.cncf.kubernetes.pod_generator_deprecated.PodDefaults.SIDECAR_CONTAINER_NAME"]], "volume (airflow.providers.cncf.kubernetes.pod_generator_deprecated.poddefaults attribute)": [[24, "airflow.providers.cncf.kubernetes.pod_generator_deprecated.PodDefaults.VOLUME"]], "volume_mount (airflow.providers.cncf.kubernetes.pod_generator_deprecated.poddefaults attribute)": [[24, "airflow.providers.cncf.kubernetes.pod_generator_deprecated.PodDefaults.VOLUME_MOUNT"]], "xcom_cmd (airflow.providers.cncf.kubernetes.pod_generator_deprecated.poddefaults attribute)": [[24, "airflow.providers.cncf.kubernetes.pod_generator_deprecated.PodDefaults.XCOM_CMD"]], "xcom_mount_path (airflow.providers.cncf.kubernetes.pod_generator_deprecated.poddefaults attribute)": [[24, "airflow.providers.cncf.kubernetes.pod_generator_deprecated.PodDefaults.XCOM_MOUNT_PATH"]], "add_sidecar() (airflow.providers.cncf.kubernetes.pod_generator_deprecated.podgenerator static method)": [[24, "airflow.providers.cncf.kubernetes.pod_generator_deprecated.PodGenerator.add_sidecar"]], "airflow.providers.cncf.kubernetes.pod_generator_deprecated": [[24, "module-airflow.providers.cncf.kubernetes.pod_generator_deprecated"]], "from_obj() (airflow.providers.cncf.kubernetes.pod_generator_deprecated.podgenerator static method)": [[24, "airflow.providers.cncf.kubernetes.pod_generator_deprecated.PodGenerator.from_obj"]], "gen_pod() (airflow.providers.cncf.kubernetes.pod_generator_deprecated.podgenerator method)": [[24, "airflow.providers.cncf.kubernetes.pod_generator_deprecated.PodGenerator.gen_pod"]], "make_safe_label_value() (in module airflow.providers.cncf.kubernetes.pod_generator_deprecated)": [[24, "airflow.providers.cncf.kubernetes.pod_generator_deprecated.make_safe_label_value"]], "make_unique_pod_id() (airflow.providers.cncf.kubernetes.pod_generator_deprecated.podgenerator static method)": [[24, "airflow.providers.cncf.kubernetes.pod_generator_deprecated.PodGenerator.make_unique_pod_id"]], "failed (airflow.providers.cncf.kubernetes.pod_launcher_deprecated.podstatus attribute)": [[25, "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodStatus.FAILED"]], "pending (airflow.providers.cncf.kubernetes.pod_launcher_deprecated.podstatus attribute)": [[25, "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodStatus.PENDING"]], "podlauncher (class in airflow.providers.cncf.kubernetes.pod_launcher_deprecated)": [[25, "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodLauncher"]], "podstatus (class in airflow.providers.cncf.kubernetes.pod_launcher_deprecated)": [[25, "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodStatus"]], "running (airflow.providers.cncf.kubernetes.pod_launcher_deprecated.podstatus attribute)": [[25, "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodStatus.RUNNING"]], "succeeded (airflow.providers.cncf.kubernetes.pod_launcher_deprecated.podstatus attribute)": [[25, "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodStatus.SUCCEEDED"]], "airflow.providers.cncf.kubernetes.pod_launcher_deprecated": [[25, "module-airflow.providers.cncf.kubernetes.pod_launcher_deprecated"]], "base_container_is_running() (airflow.providers.cncf.kubernetes.pod_launcher_deprecated.podlauncher method)": [[25, "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodLauncher.base_container_is_running"]], "delete_pod() (airflow.providers.cncf.kubernetes.pod_launcher_deprecated.podlauncher method)": [[25, "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodLauncher.delete_pod"]], "monitor_pod() (airflow.providers.cncf.kubernetes.pod_launcher_deprecated.podlauncher method)": [[25, "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodLauncher.monitor_pod"]], "parse_log_line() (airflow.providers.cncf.kubernetes.pod_launcher_deprecated.podlauncher method)": [[25, "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodLauncher.parse_log_line"]], "pod_is_running() (airflow.providers.cncf.kubernetes.pod_launcher_deprecated.podlauncher method)": [[25, "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodLauncher.pod_is_running"]], "pod_not_started() (airflow.providers.cncf.kubernetes.pod_launcher_deprecated.podlauncher method)": [[25, "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodLauncher.pod_not_started"]], "process_status() (airflow.providers.cncf.kubernetes.pod_launcher_deprecated.podlauncher method)": [[25, "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodLauncher.process_status"]], "read_pod() (airflow.providers.cncf.kubernetes.pod_launcher_deprecated.podlauncher method)": [[25, "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodLauncher.read_pod"]], "read_pod_events() (airflow.providers.cncf.kubernetes.pod_launcher_deprecated.podlauncher method)": [[25, "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodLauncher.read_pod_events"]], "read_pod_logs() (airflow.providers.cncf.kubernetes.pod_launcher_deprecated.podlauncher method)": [[25, "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodLauncher.read_pod_logs"]], "run_pod_async() (airflow.providers.cncf.kubernetes.pod_launcher_deprecated.podlauncher method)": [[25, "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodLauncher.run_pod_async"]], "start_pod() (airflow.providers.cncf.kubernetes.pod_launcher_deprecated.podlauncher method)": [[25, "airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodLauncher.start_pod"]], "airflow.providers.cncf.kubernetes.pod_template_file_examples": [[26, "module-airflow.providers.cncf.kubernetes.pod_template_file_examples"]], "airflow.providers.cncf.kubernetes.python_kubernetes_script": [[27, "module-airflow.providers.cncf.kubernetes.python_kubernetes_script"]], "remove_task_decorator() (in module airflow.providers.cncf.kubernetes.python_kubernetes_script)": [[27, "airflow.providers.cncf.kubernetes.python_kubernetes_script.remove_task_decorator"]], "write_python_script() (in module airflow.providers.cncf.kubernetes.python_kubernetes_script)": [[27, "airflow.providers.cncf.kubernetes.python_kubernetes_script.write_python_script"]], "airflow.providers.cncf.kubernetes.resource_convert.configmap": [[28, "module-airflow.providers.cncf.kubernetes.resource_convert.configmap"]], "convert_configmap() (in module airflow.providers.cncf.kubernetes.resource_convert.configmap)": [[28, "airflow.providers.cncf.kubernetes.resource_convert.configmap.convert_configmap"]], "convert_configmap_to_volume() (in module airflow.providers.cncf.kubernetes.resource_convert.configmap)": [[28, "airflow.providers.cncf.kubernetes.resource_convert.configmap.convert_configmap_to_volume"]], "airflow.providers.cncf.kubernetes.resource_convert.env_variable": [[29, "module-airflow.providers.cncf.kubernetes.resource_convert.env_variable"]], "convert_env_vars() (in module airflow.providers.cncf.kubernetes.resource_convert.env_variable)": [[29, "airflow.providers.cncf.kubernetes.resource_convert.env_variable.convert_env_vars"]], "airflow.providers.cncf.kubernetes.resource_convert": [[30, "module-airflow.providers.cncf.kubernetes.resource_convert"]], "airflow.providers.cncf.kubernetes.resource_convert.secret": [[31, "module-airflow.providers.cncf.kubernetes.resource_convert.secret"]], "convert_image_pull_secrets() (in module airflow.providers.cncf.kubernetes.resource_convert.secret)": [[31, "airflow.providers.cncf.kubernetes.resource_convert.secret.convert_image_pull_secrets"]], "convert_secret() (in module airflow.providers.cncf.kubernetes.resource_convert.secret)": [[31, "airflow.providers.cncf.kubernetes.resource_convert.secret.convert_secret"]], "secret (class in airflow.providers.cncf.kubernetes.secret)": [[32, "airflow.providers.cncf.kubernetes.secret.Secret"]], "__eq__() (airflow.providers.cncf.kubernetes.secret.secret method)": [[32, "airflow.providers.cncf.kubernetes.secret.Secret.__eq__"]], "__repr__() (airflow.providers.cncf.kubernetes.secret.secret method)": [[32, "airflow.providers.cncf.kubernetes.secret.Secret.__repr__"]], "airflow.providers.cncf.kubernetes.secret": [[32, "module-airflow.providers.cncf.kubernetes.secret"]], "attach_to_pod() (airflow.providers.cncf.kubernetes.secret.secret method)": [[32, "airflow.providers.cncf.kubernetes.secret.Secret.attach_to_pod"]], "to_env_from_secret() (airflow.providers.cncf.kubernetes.secret.secret method)": [[32, "airflow.providers.cncf.kubernetes.secret.Secret.to_env_from_secret"]], "to_env_secret() (airflow.providers.cncf.kubernetes.secret.secret method)": [[32, "airflow.providers.cncf.kubernetes.secret.Secret.to_env_secret"]], "to_volume_secret() (airflow.providers.cncf.kubernetes.secret.secret method)": [[32, "airflow.providers.cncf.kubernetes.secret.Secret.to_volume_secret"]], "airflow.providers.cncf.kubernetes.sensors": [[33, "module-airflow.providers.cncf.kubernetes.sensors"]], "failure_states (airflow.providers.cncf.kubernetes.sensors.spark_kubernetes.sparkkubernetessensor attribute)": [[34, "airflow.providers.cncf.kubernetes.sensors.spark_kubernetes.SparkKubernetesSensor.FAILURE_STATES"]], "success_states (airflow.providers.cncf.kubernetes.sensors.spark_kubernetes.sparkkubernetessensor attribute)": [[34, "airflow.providers.cncf.kubernetes.sensors.spark_kubernetes.SparkKubernetesSensor.SUCCESS_STATES"]], "sparkkubernetessensor (class in airflow.providers.cncf.kubernetes.sensors.spark_kubernetes)": [[34, "airflow.providers.cncf.kubernetes.sensors.spark_kubernetes.SparkKubernetesSensor"]], "airflow.providers.cncf.kubernetes.sensors.spark_kubernetes": [[34, "module-airflow.providers.cncf.kubernetes.sensors.spark_kubernetes"]], "hook() (airflow.providers.cncf.kubernetes.sensors.spark_kubernetes.sparkkubernetessensor method)": [[34, "airflow.providers.cncf.kubernetes.sensors.spark_kubernetes.SparkKubernetesSensor.hook"]], "poke() (airflow.providers.cncf.kubernetes.sensors.spark_kubernetes.sparkkubernetessensor method)": [[34, "airflow.providers.cncf.kubernetes.sensors.spark_kubernetes.SparkKubernetesSensor.poke"]], "template_fields (airflow.providers.cncf.kubernetes.sensors.spark_kubernetes.sparkkubernetessensor attribute)": [[34, "airflow.providers.cncf.kubernetes.sensors.spark_kubernetes.SparkKubernetesSensor.template_fields"]], "airflow.providers.cncf.kubernetes.template_rendering": [[35, "module-airflow.providers.cncf.kubernetes.template_rendering"]], "get_rendered_k8s_spec() (in module airflow.providers.cncf.kubernetes.template_rendering)": [[35, "airflow.providers.cncf.kubernetes.template_rendering.get_rendered_k8s_spec"]], "render_k8s_pod_yaml() (in module airflow.providers.cncf.kubernetes.template_rendering)": [[35, "airflow.providers.cncf.kubernetes.template_rendering.render_k8s_pod_yaml"]], "airflow.providers.cncf.kubernetes.triggers": [[36, "module-airflow.providers.cncf.kubernetes.triggers"]], "kubernetesjobtrigger (class in airflow.providers.cncf.kubernetes.triggers.job)": [[37, "airflow.providers.cncf.kubernetes.triggers.job.KubernetesJobTrigger"]], "airflow.providers.cncf.kubernetes.triggers.job": [[37, "module-airflow.providers.cncf.kubernetes.triggers.job"]], "hook() (airflow.providers.cncf.kubernetes.triggers.job.kubernetesjobtrigger method)": [[37, "airflow.providers.cncf.kubernetes.triggers.job.KubernetesJobTrigger.hook"]], "run() (airflow.providers.cncf.kubernetes.triggers.job.kubernetesjobtrigger method)": [[37, "airflow.providers.cncf.kubernetes.triggers.job.KubernetesJobTrigger.run"]], "serialize() (airflow.providers.cncf.kubernetes.triggers.job.kubernetesjobtrigger method)": [[37, "airflow.providers.cncf.kubernetes.triggers.job.KubernetesJobTrigger.serialize"]], "airflow.providers.cncf.kubernetes.triggers.kubernetes_pod": [[38, "module-airflow.providers.cncf.kubernetes.triggers.kubernetes_pod"]], "containerstate (class in airflow.providers.cncf.kubernetes.triggers.pod)": [[39, "airflow.providers.cncf.kubernetes.triggers.pod.ContainerState"]], "failed (airflow.providers.cncf.kubernetes.triggers.pod.containerstate attribute)": [[39, "airflow.providers.cncf.kubernetes.triggers.pod.ContainerState.FAILED"]], "kubernetespodtrigger (class in airflow.providers.cncf.kubernetes.triggers.pod)": [[39, "airflow.providers.cncf.kubernetes.triggers.pod.KubernetesPodTrigger"]], "running (airflow.providers.cncf.kubernetes.triggers.pod.containerstate attribute)": [[39, "airflow.providers.cncf.kubernetes.triggers.pod.ContainerState.RUNNING"]], "terminated (airflow.providers.cncf.kubernetes.triggers.pod.containerstate attribute)": [[39, "airflow.providers.cncf.kubernetes.triggers.pod.ContainerState.TERMINATED"]], "undefined (airflow.providers.cncf.kubernetes.triggers.pod.containerstate attribute)": [[39, "airflow.providers.cncf.kubernetes.triggers.pod.ContainerState.UNDEFINED"]], "waiting (airflow.providers.cncf.kubernetes.triggers.pod.containerstate attribute)": [[39, "airflow.providers.cncf.kubernetes.triggers.pod.ContainerState.WAITING"]], "airflow.providers.cncf.kubernetes.triggers.pod": [[39, "module-airflow.providers.cncf.kubernetes.triggers.pod"]], "define_container_state() (airflow.providers.cncf.kubernetes.triggers.pod.kubernetespodtrigger method)": [[39, "airflow.providers.cncf.kubernetes.triggers.pod.KubernetesPodTrigger.define_container_state"]], "hook() (airflow.providers.cncf.kubernetes.triggers.pod.kubernetespodtrigger method)": [[39, "airflow.providers.cncf.kubernetes.triggers.pod.KubernetesPodTrigger.hook"]], "run() (airflow.providers.cncf.kubernetes.triggers.pod.kubernetespodtrigger method)": [[39, "airflow.providers.cncf.kubernetes.triggers.pod.KubernetesPodTrigger.run"]], "serialize() (airflow.providers.cncf.kubernetes.triggers.pod.kubernetespodtrigger method)": [[39, "airflow.providers.cncf.kubernetes.triggers.pod.KubernetesPodTrigger.serialize"]], "should_wait() (airflow.providers.cncf.kubernetes.triggers.pod.kubernetespodtrigger static method)": [[39, "airflow.providers.cncf.kubernetes.triggers.pod.KubernetesPodTrigger.should_wait"]], "default_deletion_body (in module airflow.providers.cncf.kubernetes.utils.delete_from)": [[40, "airflow.providers.cncf.kubernetes.utils.delete_from.DEFAULT_DELETION_BODY"]], "failtodeleteerror": [[40, "airflow.providers.cncf.kubernetes.utils.delete_from.FailToDeleteError"]], "__str__() (airflow.providers.cncf.kubernetes.utils.delete_from.failtodeleteerror method)": [[40, "airflow.providers.cncf.kubernetes.utils.delete_from.FailToDeleteError.__str__"]], "airflow.providers.cncf.kubernetes.utils.delete_from": [[40, "module-airflow.providers.cncf.kubernetes.utils.delete_from"]], "delete_from_dict() (in module airflow.providers.cncf.kubernetes.utils.delete_from)": [[40, "airflow.providers.cncf.kubernetes.utils.delete_from.delete_from_dict"]], "delete_from_yaml() (in module airflow.providers.cncf.kubernetes.utils.delete_from)": [[40, "airflow.providers.cncf.kubernetes.utils.delete_from.delete_from_yaml"]], "airflow.providers.cncf.kubernetes.utils": [[41, "module-airflow.providers.cncf.kubernetes.utils"]], "airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator": [[42, "module-airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator"]], "k8s_resource_iterator() (in module airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator)": [[42, "airflow.providers.cncf.kubernetes.utils.k8s_resource_iterator.k8s_resource_iterator"]], "delete_pod (airflow.providers.cncf.kubernetes.utils.pod_manager.onfinishaction attribute)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.OnFinishAction.DELETE_POD"]], "delete_succeeded_pod (airflow.providers.cncf.kubernetes.utils.pod_manager.onfinishaction attribute)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.OnFinishAction.DELETE_SUCCEEDED_POD"]], "failed (airflow.providers.cncf.kubernetes.utils.pod_manager.podphase attribute)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodPhase.FAILED"]], "keep_pod (airflow.providers.cncf.kubernetes.utils.pod_manager.onfinishaction attribute)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.OnFinishAction.KEEP_POD"]], "onfinishaction (class in airflow.providers.cncf.kubernetes.utils.pod_manager)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.OnFinishAction"]], "pending (airflow.providers.cncf.kubernetes.utils.pod_manager.podphase attribute)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodPhase.PENDING"]], "podlaunchfailedexception": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodLaunchFailedException"]], "podlaunchtimeoutexception": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodLaunchTimeoutException"]], "podloggingstatus (class in airflow.providers.cncf.kubernetes.utils.pod_manager)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodLoggingStatus"]], "podmanager (class in airflow.providers.cncf.kubernetes.utils.pod_manager)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager"]], "podnotfoundexception": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodNotFoundException"]], "podoperatorhookprotocol (class in airflow.providers.cncf.kubernetes.utils.pod_manager)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodOperatorHookProtocol"]], "podphase (class in airflow.providers.cncf.kubernetes.utils.pod_manager)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodPhase"]], "running (airflow.providers.cncf.kubernetes.utils.pod_manager.podphase attribute)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodPhase.RUNNING"]], "succeeded (airflow.providers.cncf.kubernetes.utils.pod_manager.podphase attribute)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodPhase.SUCCEEDED"]], "airflow.providers.cncf.kubernetes.utils.pod_manager": [[43, "module-airflow.providers.cncf.kubernetes.utils.pod_manager"]], "await_container_completion() (airflow.providers.cncf.kubernetes.utils.pod_manager.podmanager method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager.await_container_completion"]], "await_pod_completion() (airflow.providers.cncf.kubernetes.utils.pod_manager.podmanager method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager.await_pod_completion"]], "await_pod_start() (airflow.providers.cncf.kubernetes.utils.pod_manager.podmanager method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager.await_pod_start"]], "await_xcom_sidecar_container_start() (airflow.providers.cncf.kubernetes.utils.pod_manager.podmanager method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager.await_xcom_sidecar_container_start"]], "container_is_completed() (in module airflow.providers.cncf.kubernetes.utils.pod_manager)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.container_is_completed"]], "container_is_running() (airflow.providers.cncf.kubernetes.utils.pod_manager.podmanager method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager.container_is_running"]], "container_is_running() (in module airflow.providers.cncf.kubernetes.utils.pod_manager)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.container_is_running"]], "container_is_succeeded() (in module airflow.providers.cncf.kubernetes.utils.pod_manager)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.container_is_succeeded"]], "container_is_terminated() (airflow.providers.cncf.kubernetes.utils.pod_manager.podmanager method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager.container_is_terminated"]], "container_is_terminated() (in module airflow.providers.cncf.kubernetes.utils.pod_manager)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.container_is_terminated"]], "core_v1_client (airflow.providers.cncf.kubernetes.utils.pod_manager.podoperatorhookprotocol property)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodOperatorHookProtocol.core_v1_client"]], "create_pod() (airflow.providers.cncf.kubernetes.utils.pod_manager.podmanager method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager.create_pod"]], "delete_pod() (airflow.providers.cncf.kubernetes.utils.pod_manager.podmanager method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager.delete_pod"]], "extract_xcom() (airflow.providers.cncf.kubernetes.utils.pod_manager.podmanager method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager.extract_xcom"]], "extract_xcom_json() (airflow.providers.cncf.kubernetes.utils.pod_manager.podmanager method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager.extract_xcom_json"]], "extract_xcom_kill() (airflow.providers.cncf.kubernetes.utils.pod_manager.podmanager method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager.extract_xcom_kill"]], "follow_container_logs() (airflow.providers.cncf.kubernetes.utils.pod_manager.podmanager method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager.follow_container_logs"]], "get_container_names() (airflow.providers.cncf.kubernetes.utils.pod_manager.podmanager method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager.get_container_names"]], "get_container_status() (in module airflow.providers.cncf.kubernetes.utils.pod_manager)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.get_container_status"]], "get_container_termination_message() (in module airflow.providers.cncf.kubernetes.utils.pod_manager)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.get_container_termination_message"]], "get_namespace() (airflow.providers.cncf.kubernetes.utils.pod_manager.podoperatorhookprotocol method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodOperatorHookProtocol.get_namespace"]], "get_pod() (airflow.providers.cncf.kubernetes.utils.pod_manager.podoperatorhookprotocol method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodOperatorHookProtocol.get_pod"]], "get_xcom_sidecar_container_image() (airflow.providers.cncf.kubernetes.utils.pod_manager.podoperatorhookprotocol method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodOperatorHookProtocol.get_xcom_sidecar_container_image"]], "get_xcom_sidecar_container_resources() (airflow.providers.cncf.kubernetes.utils.pod_manager.podoperatorhookprotocol method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodOperatorHookProtocol.get_xcom_sidecar_container_resources"]], "is_in_cluster (airflow.providers.cncf.kubernetes.utils.pod_manager.podoperatorhookprotocol property)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodOperatorHookProtocol.is_in_cluster"]], "last_log_time (airflow.providers.cncf.kubernetes.utils.pod_manager.podloggingstatus attribute)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodLoggingStatus.last_log_time"]], "parse_log_line() (airflow.providers.cncf.kubernetes.utils.pod_manager.podmanager method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager.parse_log_line"]], "read_pod() (airflow.providers.cncf.kubernetes.utils.pod_manager.podmanager method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager.read_pod"]], "read_pod_events() (airflow.providers.cncf.kubernetes.utils.pod_manager.podmanager method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager.read_pod_events"]], "read_pod_logs() (airflow.providers.cncf.kubernetes.utils.pod_manager.podmanager method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager.read_pod_logs"]], "run_pod_async() (airflow.providers.cncf.kubernetes.utils.pod_manager.podmanager method)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodManager.run_pod_async"]], "running (airflow.providers.cncf.kubernetes.utils.pod_manager.podloggingstatus attribute)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodLoggingStatus.running"]], "should_retry_start_pod() (in module airflow.providers.cncf.kubernetes.utils.pod_manager)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.should_retry_start_pod"]], "terminal_states (airflow.providers.cncf.kubernetes.utils.pod_manager.podphase attribute)": [[43, "airflow.providers.cncf.kubernetes.utils.pod_manager.PodPhase.terminal_states"]], "poddefaults (class in airflow.providers.cncf.kubernetes.utils.xcom_sidecar)": [[44, "airflow.providers.cncf.kubernetes.utils.xcom_sidecar.PodDefaults"]], "sidecar_container (airflow.providers.cncf.kubernetes.utils.xcom_sidecar.poddefaults attribute)": [[44, "airflow.providers.cncf.kubernetes.utils.xcom_sidecar.PodDefaults.SIDECAR_CONTAINER"]], "sidecar_container_name (airflow.providers.cncf.kubernetes.utils.xcom_sidecar.poddefaults attribute)": [[44, "airflow.providers.cncf.kubernetes.utils.xcom_sidecar.PodDefaults.SIDECAR_CONTAINER_NAME"]], "volume (airflow.providers.cncf.kubernetes.utils.xcom_sidecar.poddefaults attribute)": [[44, "airflow.providers.cncf.kubernetes.utils.xcom_sidecar.PodDefaults.VOLUME"]], "volume_mount (airflow.providers.cncf.kubernetes.utils.xcom_sidecar.poddefaults attribute)": [[44, "airflow.providers.cncf.kubernetes.utils.xcom_sidecar.PodDefaults.VOLUME_MOUNT"]], "xcom_cmd (airflow.providers.cncf.kubernetes.utils.xcom_sidecar.poddefaults attribute)": [[44, "airflow.providers.cncf.kubernetes.utils.xcom_sidecar.PodDefaults.XCOM_CMD"]], "xcom_mount_path (airflow.providers.cncf.kubernetes.utils.xcom_sidecar.poddefaults attribute)": [[44, "airflow.providers.cncf.kubernetes.utils.xcom_sidecar.PodDefaults.XCOM_MOUNT_PATH"]], "add_xcom_sidecar() (in module airflow.providers.cncf.kubernetes.utils.xcom_sidecar)": [[44, "airflow.providers.cncf.kubernetes.utils.xcom_sidecar.add_xcom_sidecar"]], "airflow.providers.cncf.kubernetes.utils.xcom_sidecar": [[44, "module-airflow.providers.cncf.kubernetes.utils.xcom_sidecar"]], "dag_id (in module tests.system.providers.cncf.kubernetes.example_kubernetes)": [[45, "tests.system.providers.cncf.kubernetes.example_kubernetes.DAG_ID"]], "env_id (in module tests.system.providers.cncf.kubernetes.example_kubernetes)": [[45, "tests.system.providers.cncf.kubernetes.example_kubernetes.ENV_ID"]], "affinity (in module tests.system.providers.cncf.kubernetes.example_kubernetes)": [[45, "tests.system.providers.cncf.kubernetes.example_kubernetes.affinity"]], "configmaps (in module tests.system.providers.cncf.kubernetes.example_kubernetes)": [[45, "tests.system.providers.cncf.kubernetes.example_kubernetes.configmaps"]], "init_container (in module tests.system.providers.cncf.kubernetes.example_kubernetes)": [[45, "tests.system.providers.cncf.kubernetes.example_kubernetes.init_container"]], "init_container_volume_mounts (in module tests.system.providers.cncf.kubernetes.example_kubernetes)": [[45, "tests.system.providers.cncf.kubernetes.example_kubernetes.init_container_volume_mounts"]], "init_environments (in module tests.system.providers.cncf.kubernetes.example_kubernetes)": [[45, "tests.system.providers.cncf.kubernetes.example_kubernetes.init_environments"]], "k (in module tests.system.providers.cncf.kubernetes.example_kubernetes)": [[45, "tests.system.providers.cncf.kubernetes.example_kubernetes.k"]], "port (in module tests.system.providers.cncf.kubernetes.example_kubernetes)": [[45, "tests.system.providers.cncf.kubernetes.example_kubernetes.port"]], "secret_all_keys (in module tests.system.providers.cncf.kubernetes.example_kubernetes)": [[45, "tests.system.providers.cncf.kubernetes.example_kubernetes.secret_all_keys"]], "secret_env (in module tests.system.providers.cncf.kubernetes.example_kubernetes)": [[45, "tests.system.providers.cncf.kubernetes.example_kubernetes.secret_env"]], "secret_file (in module tests.system.providers.cncf.kubernetes.example_kubernetes)": [[45, "tests.system.providers.cncf.kubernetes.example_kubernetes.secret_file"]], "test_run (in module tests.system.providers.cncf.kubernetes.example_kubernetes)": [[45, "tests.system.providers.cncf.kubernetes.example_kubernetes.test_run"]], "tests.system.providers.cncf.kubernetes.example_kubernetes": [[45, "module-tests.system.providers.cncf.kubernetes.example_kubernetes"]], "tolerations (in module tests.system.providers.cncf.kubernetes.example_kubernetes)": [[45, "tests.system.providers.cncf.kubernetes.example_kubernetes.tolerations"]], "volume (in module tests.system.providers.cncf.kubernetes.example_kubernetes)": [[45, "tests.system.providers.cncf.kubernetes.example_kubernetes.volume"]], "volume_mount (in module tests.system.providers.cncf.kubernetes.example_kubernetes)": [[45, "tests.system.providers.cncf.kubernetes.example_kubernetes.volume_mount"]], "dag_id (in module tests.system.providers.cncf.kubernetes.example_kubernetes_async)": [[46, "tests.system.providers.cncf.kubernetes.example_kubernetes_async.DAG_ID"]], "env_id (in module tests.system.providers.cncf.kubernetes.example_kubernetes_async)": [[46, "tests.system.providers.cncf.kubernetes.example_kubernetes_async.ENV_ID"]], "affinity (in module tests.system.providers.cncf.kubernetes.example_kubernetes_async)": [[46, "tests.system.providers.cncf.kubernetes.example_kubernetes_async.affinity"]], "configmaps (in module tests.system.providers.cncf.kubernetes.example_kubernetes_async)": [[46, "tests.system.providers.cncf.kubernetes.example_kubernetes_async.configmaps"]], "init_container (in module tests.system.providers.cncf.kubernetes.example_kubernetes_async)": [[46, "tests.system.providers.cncf.kubernetes.example_kubernetes_async.init_container"]], "init_container_volume_mounts (in module tests.system.providers.cncf.kubernetes.example_kubernetes_async)": [[46, "tests.system.providers.cncf.kubernetes.example_kubernetes_async.init_container_volume_mounts"]], "init_environments (in module tests.system.providers.cncf.kubernetes.example_kubernetes_async)": [[46, "tests.system.providers.cncf.kubernetes.example_kubernetes_async.init_environments"]], "k (in module tests.system.providers.cncf.kubernetes.example_kubernetes_async)": [[46, "tests.system.providers.cncf.kubernetes.example_kubernetes_async.k"]], "port (in module tests.system.providers.cncf.kubernetes.example_kubernetes_async)": [[46, "tests.system.providers.cncf.kubernetes.example_kubernetes_async.port"]], "secret_all_keys (in module tests.system.providers.cncf.kubernetes.example_kubernetes_async)": [[46, "tests.system.providers.cncf.kubernetes.example_kubernetes_async.secret_all_keys"]], "secret_env (in module tests.system.providers.cncf.kubernetes.example_kubernetes_async)": [[46, "tests.system.providers.cncf.kubernetes.example_kubernetes_async.secret_env"]], "secret_file (in module tests.system.providers.cncf.kubernetes.example_kubernetes_async)": [[46, "tests.system.providers.cncf.kubernetes.example_kubernetes_async.secret_file"]], "test_run (in module tests.system.providers.cncf.kubernetes.example_kubernetes_async)": [[46, "tests.system.providers.cncf.kubernetes.example_kubernetes_async.test_run"]], "tests.system.providers.cncf.kubernetes.example_kubernetes_async": [[46, "module-tests.system.providers.cncf.kubernetes.example_kubernetes_async"]], "tolerations (in module tests.system.providers.cncf.kubernetes.example_kubernetes_async)": [[46, "tests.system.providers.cncf.kubernetes.example_kubernetes_async.tolerations"]], "volume (in module tests.system.providers.cncf.kubernetes.example_kubernetes_async)": [[46, "tests.system.providers.cncf.kubernetes.example_kubernetes_async.volume"]], "volume_mount (in module tests.system.providers.cncf.kubernetes.example_kubernetes_async)": [[46, "tests.system.providers.cncf.kubernetes.example_kubernetes_async.volume_mount"]], "execute_in_k8s_pod() (in module tests.system.providers.cncf.kubernetes.example_kubernetes_decorator)": [[47, "tests.system.providers.cncf.kubernetes.example_kubernetes_decorator.execute_in_k8s_pod"]], "test_run (in module tests.system.providers.cncf.kubernetes.example_kubernetes_decorator)": [[47, "tests.system.providers.cncf.kubernetes.example_kubernetes_decorator.test_run"]], "tests.system.providers.cncf.kubernetes.example_kubernetes_decorator": [[47, "module-tests.system.providers.cncf.kubernetes.example_kubernetes_decorator"]], "dag_id (in module tests.system.providers.cncf.kubernetes.example_kubernetes_job)": [[48, "tests.system.providers.cncf.kubernetes.example_kubernetes_job.DAG_ID"]], "env_id (in module tests.system.providers.cncf.kubernetes.example_kubernetes_job)": [[48, "tests.system.providers.cncf.kubernetes.example_kubernetes_job.ENV_ID"]], "job_name (in module tests.system.providers.cncf.kubernetes.example_kubernetes_job)": [[48, "tests.system.providers.cncf.kubernetes.example_kubernetes_job.JOB_NAME"]], "job_namespace (in module tests.system.providers.cncf.kubernetes.example_kubernetes_job)": [[48, "tests.system.providers.cncf.kubernetes.example_kubernetes_job.JOB_NAMESPACE"]], "k8s_job (in module tests.system.providers.cncf.kubernetes.example_kubernetes_job)": [[48, "tests.system.providers.cncf.kubernetes.example_kubernetes_job.k8s_job"]], "test_run (in module tests.system.providers.cncf.kubernetes.example_kubernetes_job)": [[48, "tests.system.providers.cncf.kubernetes.example_kubernetes_job.test_run"]], "tests.system.providers.cncf.kubernetes.example_kubernetes_job": [[48, "module-tests.system.providers.cncf.kubernetes.example_kubernetes_job"]], "dag_id (in module tests.system.providers.cncf.kubernetes.example_kubernetes_resource)": [[49, "tests.system.providers.cncf.kubernetes.example_kubernetes_resource.DAG_ID"]], "env_id (in module tests.system.providers.cncf.kubernetes.example_kubernetes_resource)": [[49, "tests.system.providers.cncf.kubernetes.example_kubernetes_resource.ENV_ID"]], "pvc_conf (in module tests.system.providers.cncf.kubernetes.example_kubernetes_resource)": [[49, "tests.system.providers.cncf.kubernetes.example_kubernetes_resource.pvc_conf"]], "pvc_name (in module tests.system.providers.cncf.kubernetes.example_kubernetes_resource)": [[49, "tests.system.providers.cncf.kubernetes.example_kubernetes_resource.pvc_name"]], "t1 (in module tests.system.providers.cncf.kubernetes.example_kubernetes_resource)": [[49, "tests.system.providers.cncf.kubernetes.example_kubernetes_resource.t1"]], "test_run (in module tests.system.providers.cncf.kubernetes.example_kubernetes_resource)": [[49, "tests.system.providers.cncf.kubernetes.example_kubernetes_resource.test_run"]], "tests.system.providers.cncf.kubernetes.example_kubernetes_resource": [[49, "module-tests.system.providers.cncf.kubernetes.example_kubernetes_resource"]], "dag_id (in module tests.system.providers.cncf.kubernetes.example_spark_kubernetes)": [[50, "tests.system.providers.cncf.kubernetes.example_spark_kubernetes.DAG_ID"]], "env_id (in module tests.system.providers.cncf.kubernetes.example_spark_kubernetes)": [[50, "tests.system.providers.cncf.kubernetes.example_spark_kubernetes.ENV_ID"]], "pi_example_path (in module tests.system.providers.cncf.kubernetes.example_spark_kubernetes)": [[50, "tests.system.providers.cncf.kubernetes.example_spark_kubernetes.pi_example_path"]], "test_run (in module tests.system.providers.cncf.kubernetes.example_spark_kubernetes)": [[50, "tests.system.providers.cncf.kubernetes.example_spark_kubernetes.test_run"]], "tests.system.providers.cncf.kubernetes.example_spark_kubernetes": [[50, "module-tests.system.providers.cncf.kubernetes.example_spark_kubernetes"]], "tests.system.providers.cncf.kubernetes": [[51, "module-tests.system.providers.cncf.kubernetes"]]}}) \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/security.html b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/security.html new file mode 100644 index 00000000000..94a9645ab46 --- /dev/null +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/8.1.1/security.html @@ -0,0 +1,907 @@ + + + + + + + + + + + + Releasing security patches — apache-airflow-providers-cncf-kubernetes Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+
+
+

Releasing security patches

+

Airflow providers are released independently from Airflow itself and the information about vulnerabilities +is published separately. You can upgrade providers independently from Airflow itself, following the +instructions found in Installation from PyPI.

+

When we release Provider version, the development is always done from the main branch where we prepare +the next version. The provider uses strict SemVer versioning policy. Depending on +the scope of the change, Provider will get ‘’MAJOR’’ version upgrade when there are +breaking changes, MINOR version upgrade when there are new features or PATCHLEVEL version upgrade +when there are only bug fixes (including security bugfixes) - and this is the only version that receives +security fixes by default, so you should upgrade to latest version of the provider if you want to receive +all released security fixes.

+

The only exception to that rule is when we have a critical security fix and good reason to provide an +out-of-band release for the provider, in which case stakeholders in the provider might decide to cherry-pick +and prepare a branch for an older version of the provider following the +mixed governance model +and requires interested parties to cherry-pick and test the fixes.

+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-cncf-kubernetes/stable.txt b/docs-archive/apache-airflow-providers-cncf-kubernetes/stable.txt index da156181014..42ed2d77827 100644 --- a/docs-archive/apache-airflow-providers-cncf-kubernetes/stable.txt +++ b/docs-archive/apache-airflow-providers-cncf-kubernetes/stable.txt @@ -1 +1 @@ -8.1.0 \ No newline at end of file +8.1.1 \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/.buildinfo b/docs-archive/apache-airflow-providers-databricks/6.3.0/.buildinfo new file mode 100644 index 00000000000..12f3f28a742 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: f031a4f617c7bddc96e56799368e8798 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/hooks/databricks/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/hooks/databricks/index.html new file mode 100644 index 00000000000..09dc4b4ae0b --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/hooks/databricks/index.html @@ -0,0 +1,1894 @@ + + + + + + + + + + + + airflow.providers.databricks.hooks.databricks — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.databricks.hooks.databricks

+

Databricks hook.

+

This hook enable the submitting and running of jobs to the Databricks platform. Internally the +operators talk to the +api/2.1/jobs/run-now +endpoint <https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunNow>_ +or the api/2.1/jobs/runs/submit +endpoint.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + + + + +

RunState

Utility class for the run state concept of Databricks runs.

ClusterState

Utility class for the cluster state concept of Databricks cluster.

DatabricksHook

Interact with Databricks.

+
+
+

Attributes

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GET_CLUSTER_ENDPOINT

RESTART_CLUSTER_ENDPOINT

START_CLUSTER_ENDPOINT

TERMINATE_CLUSTER_ENDPOINT

CREATE_ENDPOINT

RESET_ENDPOINT

RUN_NOW_ENDPOINT

SUBMIT_RUN_ENDPOINT

GET_RUN_ENDPOINT

CANCEL_RUN_ENDPOINT

DELETE_RUN_ENDPOINT

REPAIR_RUN_ENDPOINT

OUTPUT_RUNS_JOB_ENDPOINT

CANCEL_ALL_RUNS_ENDPOINT

INSTALL_LIBS_ENDPOINT

UNINSTALL_LIBS_ENDPOINT

LIST_JOBS_ENDPOINT

LIST_PIPELINES_ENDPOINT

WORKSPACE_GET_STATUS_ENDPOINT

SPARK_VERSIONS_ENDPOINT

+
+
+airflow.providers.databricks.hooks.databricks.GET_CLUSTER_ENDPOINT = ('GET', 'api/2.0/clusters/get')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.RESTART_CLUSTER_ENDPOINT = ('POST', 'api/2.0/clusters/restart')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.START_CLUSTER_ENDPOINT = ('POST', 'api/2.0/clusters/start')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.TERMINATE_CLUSTER_ENDPOINT = ('POST', 'api/2.0/clusters/delete')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.CREATE_ENDPOINT = ('POST', 'api/2.1/jobs/create')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.RESET_ENDPOINT = ('POST', 'api/2.1/jobs/reset')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.RUN_NOW_ENDPOINT = ('POST', 'api/2.1/jobs/run-now')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.SUBMIT_RUN_ENDPOINT = ('POST', 'api/2.1/jobs/runs/submit')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.GET_RUN_ENDPOINT = ('GET', 'api/2.1/jobs/runs/get')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.CANCEL_RUN_ENDPOINT = ('POST', 'api/2.1/jobs/runs/cancel')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.DELETE_RUN_ENDPOINT = ('POST', 'api/2.1/jobs/runs/delete')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.REPAIR_RUN_ENDPOINT = ('POST', 'api/2.1/jobs/runs/repair')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.OUTPUT_RUNS_JOB_ENDPOINT = ('GET', 'api/2.1/jobs/runs/get-output')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.CANCEL_ALL_RUNS_ENDPOINT = ('POST', 'api/2.1/jobs/runs/cancel-all')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.INSTALL_LIBS_ENDPOINT = ('POST', 'api/2.0/libraries/install')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.UNINSTALL_LIBS_ENDPOINT = ('POST', 'api/2.0/libraries/uninstall')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.LIST_JOBS_ENDPOINT = ('GET', 'api/2.1/jobs/list')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.LIST_PIPELINES_ENDPOINT = ('GET', 'api/2.0/pipelines')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.WORKSPACE_GET_STATUS_ENDPOINT = ('GET', 'api/2.0/workspace/get-status')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks.SPARK_VERSIONS_ENDPOINT = ('GET', 'api/2.0/clusters/spark-versions')[source]
+
+ +
+
+class airflow.providers.databricks.hooks.databricks.RunState(life_cycle_state, result_state='', state_message='', *args, **kwargs)[source]
+

Utility class for the run state concept of Databricks runs.

+
+
+
+
+property is_terminal: bool[source]
+

True if the current state is a terminal state.

+
+
+
+ +
+
+property is_successful: bool[source]
+

True if the result state is SUCCESS.

+
+
+
+ +
+
+RUN_LIFE_CYCLE_STATES = ['PENDING', 'RUNNING', 'TERMINATING', 'TERMINATED', 'SKIPPED', 'INTERNAL_ERROR', 'QUEUED'][source]
+
+ +
+
+__eq__(other)[source]
+

Return self==value.

+
+
+
+ +
+
+__repr__()[source]
+

Return repr(self).

+
+
+
+ +
+
+to_json()[source]
+
+
+
+ +
+
+classmethod from_json(data)[source]
+
+
+
+ +
+ +
+
+class airflow.providers.databricks.hooks.databricks.ClusterState(state='', state_message='', *args, **kwargs)[source]
+

Utility class for the cluster state concept of Databricks cluster.

+
+
+
+
+property is_terminal: bool[source]
+

True if the current state is a terminal state.

+
+
+
+ +
+
+property is_running: bool[source]
+

True if the current state is running.

+
+
+
+ +
+
+CLUSTER_LIFE_CYCLE_STATES = ['PENDING', 'RUNNING', 'RESTARTING', 'RESIZING', 'TERMINATING', 'TERMINATED', 'ERROR', 'UNKNOWN'][source]
+
+ +
+
+__eq__(other)[source]
+

Return self==value.

+
+
+
+ +
+
+__repr__()[source]
+

Return repr(self).

+
+
+
+ +
+
+to_json()[source]
+
+
+
+ +
+
+classmethod from_json(data)[source]
+
+
+
+ +
+ +
+
+class airflow.providers.databricks.hooks.databricks.DatabricksHook(databricks_conn_id=BaseDatabricksHook.default_conn_name, timeout_seconds=180, retry_limit=3, retry_delay=1.0, retry_args=None, caller='DatabricksHook')[source]
+

Bases: airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook

+

Interact with Databricks.

+
+
Parameters
+
    +
  • databricks_conn_id (str) -- Reference to the Databricks connection.

  • +
  • timeout_seconds (int) -- The amount of time in seconds the requests library +will wait before timing-out.

  • +
  • retry_limit (int) -- The number of times to retry the connection in case of +service outages.

  • +
  • retry_delay (float) -- The number of seconds to wait between retries (it +might be a floating point number).

  • +
  • retry_args (dict[Any, Any] | None) -- An optional dictionary with arguments passed to tenacity.Retrying class.

  • +
+
+
+
+
+hook_name = 'Databricks'[source]
+
+ +
+
+create_job(json)[source]
+

Call the api/2.1/jobs/create endpoint.

+
+
Parameters
+

json (dict) -- The data used in the body of the request to the create endpoint.

+
+
Returns
+

the job_id as an int

+
+
Return type
+

int

+
+
+
+ +
+
+reset_job(job_id, json)[source]
+

Call the api/2.1/jobs/reset endpoint.

+
+
Parameters
+

json (dict) -- The data used in the new_settings of the request to the reset endpoint.

+
+
+
+ +
+
+run_now(json)[source]
+

Call the api/2.1/jobs/run-now endpoint.

+
+
Parameters
+

json (dict) -- The data used in the body of the request to the run-now endpoint.

+
+
Returns
+

the run_id as an int

+
+
Return type
+

int

+
+
+
+ +
+
+submit_run(json)[source]
+

Call the api/2.1/jobs/runs/submit endpoint.

+
+
Parameters
+

json (dict) -- The data used in the body of the request to the submit endpoint.

+
+
Returns
+

the run_id as an int

+
+
Return type
+

int

+
+
+
+ +
+
+list_jobs(limit=25, expand_tasks=False, job_name=None, page_token=None)[source]
+

List the jobs in the Databricks Job Service.

+
+
Parameters
+
    +
  • limit (int) -- The limit/batch size used to retrieve jobs.

  • +
  • expand_tasks (bool) -- Whether to include task and cluster details in the response.

  • +
  • job_name (str | None) -- Optional name of a job to search.

  • +
  • page_token (str | None) -- The optional page token pointing at the first first job to return.

  • +
+
+
Returns
+

A list of jobs.

+
+
Return type
+

list[dict[str, Any]]

+
+
+
+ +
+
+find_job_id_by_name(job_name)[source]
+

Find job id by its name; if there are multiple jobs with the same name, raise AirflowException.

+
+
Parameters
+

job_name (str) -- The name of the job to look up.

+
+
Returns
+

The job_id as an int or None if no job was found.

+
+
Return type
+

int | None

+
+
+
+ +
+
+list_pipelines(batch_size=25, pipeline_name=None, notebook_path=None)[source]
+

List the pipelines in Databricks Delta Live Tables.

+
+
Parameters
+
    +
  • batch_size (int) -- The limit/batch size used to retrieve pipelines.

  • +
  • pipeline_name (str | None) -- Optional name of a pipeline to search. Cannot be combined with path.

  • +
  • notebook_path (str | None) -- Optional notebook of a pipeline to search. Cannot be combined with name.

  • +
+
+
Returns
+

A list of pipelines.

+
+
Return type
+

list[dict[str, Any]]

+
+
+
+ +
+
+find_pipeline_id_by_name(pipeline_name)[source]
+

Find pipeline id by its name; if multiple pipelines with the same name, raise AirflowException.

+
+
Parameters
+

pipeline_name (str) -- The name of the pipeline to look up.

+
+
Returns
+

The pipeline_id as a GUID string or None if no pipeline was found.

+
+
Return type
+

str | None

+
+
+
+ +
+
+get_run_page_url(run_id)[source]
+

Retrieve run_page_url.

+
+
Parameters
+

run_id (int) -- id of the run

+
+
Returns
+

URL of the run page

+
+
Return type
+

str

+
+
+
+ +
+
+async a_get_run_page_url(run_id)[source]
+

Async version of get_run_page_url().

+
+
Parameters
+

run_id (int) -- id of the run

+
+
Returns
+

URL of the run page

+
+
Return type
+

str

+
+
+
+ +
+
+get_job_id(run_id)[source]
+

Retrieve job_id from run_id.

+
+
Parameters
+

run_id (int) -- id of the run

+
+
Returns
+

Job id for given Databricks run

+
+
Return type
+

int

+
+
+
+ +
+
+get_run_state(run_id)[source]
+

Retrieve run state of the run.

+

Please note that any Airflow tasks that call the get_run_state method will result in +failure unless you have enabled xcom pickling. This can be done using the following +environment variable: AIRFLOW__CORE__ENABLE_XCOM_PICKLING

+

If you do not want to enable xcom pickling, use the get_run_state_str method to get +a string describing state, or get_run_state_lifecycle, get_run_state_result, or +get_run_state_message to get individual components of the run state.

+
+
Parameters
+

run_id (int) -- id of the run

+
+
Returns
+

state of the run

+
+
Return type
+

RunState

+
+
+
+ +
+
+async a_get_run_state(run_id)[source]
+

Async version of get_run_state().

+
+
Parameters
+

run_id (int) -- id of the run

+
+
Returns
+

state of the run

+
+
Return type
+

RunState

+
+
+
+ +
+
+get_run(run_id)[source]
+

Retrieve run information.

+
+
Parameters
+

run_id (int) -- id of the run

+
+
Returns
+

state of the run

+
+
Return type
+

dict[str, Any]

+
+
+
+ +
+
+async a_get_run(run_id)[source]
+

Async version of get_run.

+
+
Parameters
+

run_id (int) -- id of the run

+
+
Returns
+

state of the run

+
+
Return type
+

dict[str, Any]

+
+
+
+ +
+
+get_run_state_str(run_id)[source]
+

Return the string representation of RunState.

+
+
Parameters
+

run_id (int) -- id of the run

+
+
Returns
+

string describing run state

+
+
Return type
+

str

+
+
+
+ +
+
+get_run_state_lifecycle(run_id)[source]
+

Return the lifecycle state of the run.

+
+
Parameters
+

run_id (int) -- id of the run

+
+
Returns
+

string with lifecycle state

+
+
Return type
+

str

+
+
+
+ +
+
+get_run_state_result(run_id)[source]
+

Return the resulting state of the run.

+
+
Parameters
+

run_id (int) -- id of the run

+
+
Returns
+

string with resulting state

+
+
Return type
+

str

+
+
+
+ +
+
+get_run_state_message(run_id)[source]
+

Return the state message for the run.

+
+
Parameters
+

run_id (int) -- id of the run

+
+
Returns
+

string with state message

+
+
Return type
+

str

+
+
+
+ +
+
+get_run_output(run_id)[source]
+

Retrieve run output of the run.

+
+
Parameters
+

run_id (int) -- id of the run

+
+
Returns
+

output of the run

+
+
Return type
+

dict

+
+
+
+ +
+
+cancel_run(run_id)[source]
+

Cancel the run.

+
+
Parameters
+

run_id (int) -- id of the run

+
+
+
+ +
+
+cancel_all_runs(job_id)[source]
+

Cancel all active runs of a job asynchronously.

+
+
Parameters
+

job_id (int) -- The canonical identifier of the job to cancel all runs of

+
+
+
+ +
+
+delete_run(run_id)[source]
+

Delete a non-active run.

+
+
Parameters
+

run_id (int) -- id of the run

+
+
+
+ +
+
+repair_run(json)[source]
+

Re-run one or more tasks.

+
+
Parameters
+

json (dict) -- repair a job run.

+
+
+
+ +
+
+get_latest_repair_id(run_id)[source]
+

Get latest repair id if any exist for run_id else None.

+
+
+
+ +
+
+get_cluster_state(cluster_id)[source]
+

Retrieve run state of the cluster.

+
+
Parameters
+

cluster_id (str) -- id of the cluster

+
+
Returns
+

state of the cluster

+
+
Return type
+

ClusterState

+
+
+
+ +
+
+async a_get_cluster_state(cluster_id)[source]
+

Async version of get_cluster_state.

+
+
Parameters
+

cluster_id (str) -- id of the cluster

+
+
Returns
+

state of the cluster

+
+
Return type
+

ClusterState

+
+
+
+ +
+
+restart_cluster(json)[source]
+

Restarts the cluster.

+
+
Parameters
+

json (dict) -- json dictionary containing cluster specification.

+
+
+
+ +
+
+start_cluster(json)[source]
+

Start the cluster.

+
+
Parameters
+

json (dict) -- json dictionary containing cluster specification.

+
+
+
+ +
+
+terminate_cluster(json)[source]
+

Terminate the cluster.

+
+
Parameters
+

json (dict) -- json dictionary containing cluster specification.

+
+
+
+ +
+
+install(json)[source]
+

Install libraries on the cluster.

+

Utility function to call the 2.0/libraries/install endpoint.

+
+
Parameters
+

json (dict) -- json dictionary containing cluster_id and an array of library

+
+
+
+ +
+
+uninstall(json)[source]
+

Uninstall libraries on the cluster.

+

Utility function to call the 2.0/libraries/uninstall endpoint.

+
+
Parameters
+

json (dict) -- json dictionary containing cluster_id and an array of library

+
+
+
+ +
+
+update_repo(repo_id, json)[source]
+

Update given Databricks Repos.

+
+
Parameters
+
    +
  • repo_id (str) -- ID of Databricks Repos

  • +
  • json (dict[str, Any]) -- payload

  • +
+
+
Returns
+

metadata from update

+
+
Return type
+

dict

+
+
+
+ +
+
+delete_repo(repo_id)[source]
+

Delete given Databricks Repos.

+
+
Parameters
+

repo_id (str) -- ID of Databricks Repos

+
+
Returns
+

+
+
+
+ +
+
+create_repo(json)[source]
+

Create a Databricks Repos.

+
+
Parameters
+

json (dict[str, Any]) -- payload

+
+
Returns
+

+
+
Return type
+

dict

+
+
+
+ +
+
+get_repo_by_path(path)[source]
+

Obtain Repos ID by path.

+
+
Parameters
+

path (str) -- path to a repository

+
+
Returns
+

Repos ID if it exists, None if doesn't.

+
+
Return type
+

str | None

+
+
+
+ +
+
+update_job_permission(job_id, json)[source]
+

Update databricks job permission.

+
+
Parameters
+
    +
  • job_id (int) -- job id

  • +
  • json (dict[str, Any]) -- payload

  • +
+
+
Returns
+

json containing permission specification

+
+
Return type
+

dict

+
+
+
+ +
+
+test_connection()[source]
+

Test the Databricks connectivity from UI.

+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/hooks/databricks_base/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/hooks/databricks_base/index.html new file mode 100644 index 00000000000..fa79d93d3d3 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/hooks/databricks_base/index.html @@ -0,0 +1,1108 @@ + + + + + + + + + + + + airflow.providers.databricks.hooks.databricks_base — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.databricks.hooks.databricks_base

+

Databricks hook.

+

This hook enable the submitting and running of jobs to the Databricks platform. Internally the +operators talk to the api/2.0/jobs/runs/submit +endpoint.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + +

BaseDatabricksHook

Base for interaction with Databricks.

BearerAuth

aiohttp only ships BasicAuth, for Bearer auth we need a subclass of BasicAuth.

+
+
+

Attributes

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +

AZURE_DEFAULT_AD_ENDPOINT

AZURE_TOKEN_SERVICE_URL

AZURE_METADATA_SERVICE_TOKEN_URL

AZURE_METADATA_SERVICE_INSTANCE_URL

TOKEN_REFRESH_LEAD_TIME

AZURE_MANAGEMENT_ENDPOINT

DEFAULT_DATABRICKS_SCOPE

OIDC_TOKEN_SERVICE_URL

+
+
+airflow.providers.databricks.hooks.databricks_base.AZURE_DEFAULT_AD_ENDPOINT = 'https://login.microsoftonline.com'[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks_base.AZURE_TOKEN_SERVICE_URL = '{}/{}/oauth2/token'[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks_base.AZURE_METADATA_SERVICE_TOKEN_URL = 'http://169.254.169.254/metadata/identity/oauth2/token'[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks_base.AZURE_METADATA_SERVICE_INSTANCE_URL = 'http://169.254.169.254/metadata/instance'[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks_base.TOKEN_REFRESH_LEAD_TIME = 120[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks_base.AZURE_MANAGEMENT_ENDPOINT = 'https://management.core.windows.net/'[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks_base.DEFAULT_DATABRICKS_SCOPE = '2ff814a6-3304-4ab8-85cb-cd0e6f879c1d'[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks_base.OIDC_TOKEN_SERVICE_URL = '{}/oidc/v1/token'[source]
+
+ +
+
+class airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook(databricks_conn_id=default_conn_name, timeout_seconds=180, retry_limit=3, retry_delay=1.0, retry_args=None, caller='Unknown')[source]
+

Bases: airflow.hooks.base.BaseHook

+

Base for interaction with Databricks.

+
+
Parameters
+
    +
  • databricks_conn_id (str) -- Reference to the Databricks connection.

  • +
  • timeout_seconds (int) -- The amount of time in seconds the requests library +will wait before timing-out.

  • +
  • retry_limit (int) -- The number of times to retry the connection in case of +service outages.

  • +
  • retry_delay (float) -- The number of seconds to wait between retries (it +might be a floating point number).

  • +
  • retry_args (dict[Any, Any] | None) -- An optional dictionary with arguments passed to tenacity.Retrying class.

  • +
+
+
+
+
+conn_name_attr: str = 'databricks_conn_id'[source]
+
+ +
+
+default_conn_name = 'databricks_default'[source]
+
+ +
+
+conn_type = 'databricks'[source]
+
+ +
+
+extra_parameters = ['token', 'host', 'use_azure_managed_identity', 'azure_ad_endpoint', 'azure_resource_id',...[source]
+
+ +
+
+databricks_conn()[source]
+
+
+
+ +
+
+get_conn()[source]
+

Return connection for the hook.

+
+
+
+ +
+
+user_agent_header()[source]
+
+
+
+ +
+
+user_agent_value()[source]
+
+
+
+ +
+
+host()[source]
+
+
+
+ +
+
+async __aenter__()[source]
+
+ +
+
+async __aexit__(*err)[source]
+
+ +
+ +
+
+class airflow.providers.databricks.hooks.databricks_base.BearerAuth(token)[source]
+

Bases: aiohttp.BasicAuth

+

aiohttp only ships BasicAuth, for Bearer auth we need a subclass of BasicAuth.

+
+
+
+
+encode()[source]
+

Encode credentials.

+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/hooks/databricks_sql/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/hooks/databricks_sql/index.html new file mode 100644 index 00000000000..5792eeab254 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/hooks/databricks_sql/index.html @@ -0,0 +1,1034 @@ + + + + + + + + + + + + airflow.providers.databricks.hooks.databricks_sql — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.databricks.hooks.databricks_sql

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

DatabricksSqlHook

Hook to interact with Databricks SQL.

+
+
+

Attributes

+ ++++ + + + + + + + + +

LIST_SQL_ENDPOINTS_ENDPOINT

T

+
+
+airflow.providers.databricks.hooks.databricks_sql.LIST_SQL_ENDPOINTS_ENDPOINT = ('GET', 'api/2.0/sql/endpoints')[source]
+
+ +
+
+airflow.providers.databricks.hooks.databricks_sql.T[source]
+
+ +
+
+class airflow.providers.databricks.hooks.databricks_sql.DatabricksSqlHook(databricks_conn_id=BaseDatabricksHook.default_conn_name, http_path=None, sql_endpoint_name=None, session_configuration=None, http_headers=None, catalog=None, schema=None, caller='DatabricksSqlHook', return_tuple=False, **kwargs)[source]
+

Bases: airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook, airflow.providers.common.sql.hooks.sql.DbApiHook

+

Hook to interact with Databricks SQL.

+
+
Parameters
+
    +
  • databricks_conn_id (str) -- Reference to the +Databricks connection.

  • +
  • http_path (str | None) -- Optional string specifying HTTP path of Databricks SQL Endpoint or cluster. +If not specified, it should be either specified in the Databricks connection's extra parameters, +or sql_endpoint_name must be specified.

  • +
  • sql_endpoint_name (str | None) -- Optional name of Databricks SQL Endpoint. If not specified, http_path +must be provided as described above.

  • +
  • session_configuration (dict[str, str] | None) -- An optional dictionary of Spark session parameters. Defaults to None. +If not specified, it could be specified in the Databricks connection's extra parameters.

  • +
  • http_headers (list[tuple[str, str]] | None) -- An optional list of (k, v) pairs that will be set as HTTP headers +on every request

  • +
  • catalog (str | None) -- An optional initial catalog to use. Requires DBR version 9.0+

  • +
  • schema (str | None) -- An optional initial schema to use. Requires DBR version 9.0+

  • +
  • return_tuple (bool) -- Return a namedtuple object instead of a databricks.sql.Row object. Default +to False. In a future release of the provider, this will become True by default. This parameter +ensures backward-compatibility during the transition phase to common tuple objects for all hooks based +on DbApiHook. This flag will also be removed in a future release.

  • +
  • kwargs -- Additional parameters internal to Databricks SQL Connector parameters

  • +
+
+
+
+
+hook_name = 'Databricks SQL'[source]
+
+ +
+
+get_conn()[source]
+

Return a Databricks SQL connection object.

+
+
+
+ +
+
+run(sql: str | Iterable[str], autocommit: bool = ..., parameters: Iterable | Mapping[str, Any] | None = ..., handler: None = ..., split_statements: bool = ..., return_last: bool = ...) None[source]
+
+run(sql: str | Iterable[str], autocommit: bool = ..., parameters: Iterable | Mapping[str, Any] | None = ..., handler: Callable[[Any], T] = ..., split_statements: bool = ..., return_last: bool = ...) tuple | list[tuple] | list[list[tuple] | tuple] | None
+

Run a command or a list of commands.

+

Pass a list of SQL statements to the SQL parameter to get them to +execute sequentially.

+
+
Parameters
+
    +
  • sql -- the sql statement to be executed (str) or a list of +sql statements to execute

  • +
  • autocommit -- What to set the connection's autocommit setting to +before executing the query. Note that currently there is no commit functionality +in Databricks SQL so this flag has no effect.

  • +
  • parameters -- The parameters to render the SQL query with.

  • +
  • handler -- The result handler which is called with the result of each statement.

  • +
  • split_statements -- Whether to split a single SQL string into statements and run separately

  • +
  • return_last -- Whether to return result for only last statement or for all after split

  • +
+
+
Returns
+

return only result of the LAST SQL expression if handler was provided unless return_last +is set to False.

+
+
+
+ +
+
+abstract bulk_dump(table, tmp_file)[source]
+

Dump a database table into a tab-delimited file.

+
+
Parameters
+
    +
  • table -- The name of the source table

  • +
  • tmp_file -- The path of the target file

  • +
+
+
+
+ +
+
+abstract bulk_load(table, tmp_file)[source]
+

Load a tab-delimited file into a database table.

+
+
Parameters
+
    +
  • table -- The name of the target table

  • +
  • tmp_file -- The path of the file to load into the table

  • +
+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/hooks/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/hooks/index.html new file mode 100644 index 00000000000..915f650916b --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/hooks/index.html @@ -0,0 +1,881 @@ + + + + + + + + + + + + airflow.providers.databricks.hooks — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/index.html new file mode 100644 index 00000000000..03def3cff96 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/index.html @@ -0,0 +1,913 @@ + + + + + + + + + + + + airflow.providers.databricks — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/operators/databricks/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/operators/databricks/index.html new file mode 100644 index 00000000000..45b4e5b48bb --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/operators/databricks/index.html @@ -0,0 +1,1559 @@ + + + + + + + + + + + + airflow.providers.databricks.operators.databricks — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.databricks.operators.databricks

+

This module contains Databricks operators.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + + + + + + + + + + + + + +

DatabricksJobRunLink

Constructs a link to monitor a Databricks Job Run.

DatabricksCreateJobsOperator

Creates (or resets) a Databricks job using the API endpoint.

DatabricksSubmitRunOperator

Submits a Spark job run to Databricks using the api/2.1/jobs/runs/submit API endpoint.

DatabricksSubmitRunDeferrableOperator

Deferrable version of DatabricksSubmitRunOperator.

DatabricksRunNowOperator

Runs an existing Spark job run to Databricks using the api/2.1/jobs/run-now API endpoint.

DatabricksRunNowDeferrableOperator

Deferrable version of DatabricksRunNowOperator.

+
+
+

Attributes

+ ++++ + + + + + + + + + + + + + + +

DEFER_METHOD_NAME

XCOM_RUN_ID_KEY

XCOM_JOB_ID_KEY

XCOM_RUN_PAGE_URL_KEY

+
+
+airflow.providers.databricks.operators.databricks.DEFER_METHOD_NAME = 'execute_complete'[source]
+
+ +
+
+airflow.providers.databricks.operators.databricks.XCOM_RUN_ID_KEY = 'run_id'[source]
+
+ +
+
+airflow.providers.databricks.operators.databricks.XCOM_JOB_ID_KEY = 'job_id'[source]
+
+ +
+
+airflow.providers.databricks.operators.databricks.XCOM_RUN_PAGE_URL_KEY = 'run_page_url'[source]
+
+ +
+ +

Bases: airflow.models.BaseOperatorLink

+

Constructs a link to monitor a Databricks Job Run.

+
+
+name = 'See Databricks Job Run'[source]
+
+ +
+ +

Link to external system.

+

Note: The old signature of this function was (self, operator, dttm: datetime). That is still +supported at runtime but is deprecated.

+
+
Parameters
+
+
+
Returns
+

link to external system

+
+
Return type
+

str

+
+
+
+ +
+ +
+
+class airflow.providers.databricks.operators.databricks.DatabricksCreateJobsOperator(*, json=None, name=None, tags=None, tasks=None, job_clusters=None, email_notifications=None, webhook_notifications=None, timeout_seconds=None, schedule=None, max_concurrent_runs=None, git_source=None, access_control_list=None, databricks_conn_id='databricks_default', polling_period_seconds=30, databricks_retry_limit=3, databricks_retry_delay=1, databricks_retry_args=None, **kwargs)[source]
+

Bases: airflow.models.BaseOperator

+

Creates (or resets) a Databricks job using the API endpoint.

+ +
+
Parameters
+
    +
  • json (Any | None) --

    A JSON object containing API parameters which will be passed +directly to the api/2.1/jobs/create endpoint. The other named parameters +(i.e. name, tags, tasks, etc.) to this operator will +be merged with this json dictionary if they are provided. +If there are conflicts during the merge, the named parameters will +take precedence and override the top level json keys. (templated)

    +
    +

    See also

    +

    For more information about templating see Jinja Templating.

    +
    +

  • +
  • name (str | None) -- An optional name for the job.

  • +
  • tags (dict[str, str] | None) -- A map of tags associated with the job.

  • +
  • tasks (list[dict] | None) -- A list of task specifications to be executed by this job. +Array of objects (JobTaskSettings).

  • +
  • job_clusters (list[dict] | None) -- A list of job cluster specifications that can be shared and reused by +tasks of this job. Array of objects (JobCluster).

  • +
  • email_notifications (dict | None) -- Object (JobEmailNotifications).

  • +
  • webhook_notifications (dict | None) -- Object (WebhookNotifications).

  • +
  • timeout_seconds (int | None) -- An optional timeout applied to each run of this job.

  • +
  • schedule (dict | None) -- Object (CronSchedule).

  • +
  • max_concurrent_runs (int | None) -- An optional maximum allowed number of concurrent runs of the job.

  • +
  • git_source (dict | None) -- An optional specification for a remote repository containing the notebooks +used by this job's notebook tasks. Object (GitSource).

  • +
  • access_control_list (list[dict] | None) --

    List of permissions to set on the job. Array of object +(AccessControlRequestForUser) or object (AccessControlRequestForGroup) or object +(AccessControlRequestForServicePrincipal).

    +
    +

    See also

    +

    This will only be used on create. In order to reset ACL consider using the Databricks +UI.

    +
    +

  • +
  • databricks_conn_id (str) -- Reference to the +Databricks connection. (templated)

  • +
  • polling_period_seconds (int) -- Controls the rate which we poll for the result of +this run. By default the operator will poll every 30 seconds.

  • +
  • databricks_retry_limit (int) -- Amount of times retry if the Databricks backend is +unreachable. Its value must be greater than or equal to 1.

  • +
  • databricks_retry_delay (int) -- Number of seconds to wait between retries (it +might be a floating point number).

  • +
  • databricks_retry_args (dict[Any, Any] | None) -- An optional dictionary with arguments passed to tenacity.Retrying class.

  • +
+
+
+
+
+template_fields: Sequence[str] = ('json', 'databricks_conn_id')[source]
+
+ +
+
+ui_color = '#1CB1C2'[source]
+
+ +
+
+ui_fgcolor = '#fff'[source]
+
+ +
+
+execute(context)[source]
+

Derive when creating an operator.

+

Context is the same dictionary used as when rendering jinja templates.

+

Refer to get_template_context for more context.

+
+
+
+ +
+ +
+
+class airflow.providers.databricks.operators.databricks.DatabricksSubmitRunOperator(*, json=None, tasks=None, spark_jar_task=None, notebook_task=None, spark_python_task=None, spark_submit_task=None, pipeline_task=None, dbt_task=None, new_cluster=None, existing_cluster_id=None, libraries=None, run_name=None, timeout_seconds=None, databricks_conn_id='databricks_default', polling_period_seconds=30, databricks_retry_limit=3, databricks_retry_delay=1, databricks_retry_args=None, do_xcom_push=True, idempotency_token=None, access_control_list=None, wait_for_termination=True, git_source=None, deferrable=conf.getboolean('operators', 'default_deferrable', fallback=False), **kwargs)[source]
+

Bases: airflow.models.BaseOperator

+

Submits a Spark job run to Databricks using the api/2.1/jobs/runs/submit API endpoint.

+

See: https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunsSubmit

+

There are three ways to instantiate this operator.

+
+

See also

+

For more information on how to use this operator, take a look at the guide: +DatabricksSubmitRunOperator

+
+
+
Parameters
+
    +
  • tasks (list[object] | None) --

    Array of Objects(RunSubmitTaskSettings) <= 100 items.

    + +

  • +
  • json (Any | None) --

    A JSON object containing API parameters which will be passed +directly to the api/2.1/jobs/runs/submit endpoint. The other named parameters +(i.e. spark_jar_task, notebook_task..) to this operator will +be merged with this json dictionary if they are provided. +If there are conflicts during the merge, the named parameters will +take precedence and override the top level json keys. (templated)

    + +

  • +
  • spark_jar_task (dict[str, str] | None) --

    The main class and parameters for the JAR task. Note that +the actual JAR is specified in the libraries. +EITHER spark_jar_task OR notebook_task OR spark_python_task +OR spark_submit_task OR pipeline_task OR dbt_task should be specified. +This field will be templated.

    + +

  • +
  • notebook_task (dict[str, str] | None) --

    The notebook path and parameters for the notebook task. +EITHER spark_jar_task OR notebook_task OR spark_python_task +OR spark_submit_task OR pipeline_task OR dbt_task should be specified. +This field will be templated.

    + +

  • +
  • spark_python_task (dict[str, str | list[str]] | None) --

    The python file path and parameters to run the python file with. +EITHER spark_jar_task OR notebook_task OR spark_python_task +OR spark_submit_task OR pipeline_task OR dbt_task should be specified. +This field will be templated.

    + +

  • +
  • spark_submit_task (dict[str, list[str]] | None) --

    Parameters needed to run a spark-submit command. +EITHER spark_jar_task OR notebook_task OR spark_python_task +OR spark_submit_task OR pipeline_task OR dbt_task should be specified. +This field will be templated.

    + +

  • +
  • pipeline_task (dict[str, str] | None) --

    Parameters needed to execute a Delta Live Tables pipeline task. +The provided dictionary must contain at least pipeline_id field! +EITHER spark_jar_task OR notebook_task OR spark_python_task +OR spark_submit_task OR pipeline_task OR dbt_task should be specified. +This field will be templated.

    + +

  • +
  • dbt_task (dict[str, str | list[str]] | None) -- Parameters needed to execute a dbt task. +The provided dictionary must contain at least the commands field and the +git_source parameter also needs to be set. +EITHER spark_jar_task OR notebook_task OR spark_python_task +OR spark_submit_task OR pipeline_task OR dbt_task should be specified. +This field will be templated.

  • +
  • new_cluster (dict[str, object] | None) --

    Specs for a new cluster on which this task will be run. +EITHER new_cluster OR existing_cluster_id should be specified +(except when pipeline_task is used). +This field will be templated.

    + +

  • +
  • existing_cluster_id (str | None) -- ID for existing cluster on which to run this task. +EITHER new_cluster OR existing_cluster_id should be specified +(except when pipeline_task is used). +This field will be templated.

  • +
  • libraries (list[dict[str, Any]] | None) --

    Libraries which this run will use. +This field will be templated.

    + +

  • +
  • run_name (str | None) -- The run name used for this task. +By default this will be set to the Airflow task_id. This task_id is a +required parameter of the superclass BaseOperator. +This field will be templated.

  • +
  • idempotency_token (str | None) -- an optional token that can be used to guarantee the idempotency of job run +requests. If a run with the provided token already exists, the request does not create a new run but +returns the ID of the existing run instead. This token must have at most 64 characters.

  • +
  • access_control_list (list[dict[str, str]] | None) -- optional list of dictionaries representing Access Control List (ACL) for +a given job run. Each dictionary consists of following field - specific subject (user_name for +users, or group_name for groups), and permission_level for that subject. See Jobs API +documentation for more details.

  • +
  • wait_for_termination (bool) -- if we should wait for termination of the job run. True by default.

  • +
  • timeout_seconds (int | None) -- The timeout for this run. By default a value of 0 is used +which means to have no timeout. +This field will be templated.

  • +
  • databricks_conn_id (str) -- Reference to the Databricks connection. +By default and in the common case this will be databricks_default. To use +token based authentication, provide the key token in the extra field for the +connection and create the key host and leave the host field empty. (templated)

  • +
  • polling_period_seconds (int) -- Controls the rate which we poll for the result of +this run. By default the operator will poll every 30 seconds.

  • +
  • databricks_retry_limit (int) -- Amount of times retry if the Databricks backend is +unreachable. Its value must be greater than or equal to 1.

  • +
  • databricks_retry_delay (int) -- Number of seconds to wait between retries (it +might be a floating point number).

  • +
  • databricks_retry_args (dict[Any, Any] | None) -- An optional dictionary with arguments passed to tenacity.Retrying class.

  • +
  • do_xcom_push (bool) -- Whether we should push run_id and run_page_url to xcom.

  • +
  • git_source (dict[str, str] | None) -- Optional specification of a remote git repository from which +supported task types are retrieved.

  • +
  • deferrable (bool) --

    Run operator in the deferrable mode.

    + +

  • +
+
+
+
+
+template_fields: Sequence[str] = ('json', 'databricks_conn_id')[source]
+
+ +
+
+template_ext: Sequence[str] = ('.json-tpl',)[source]
+
+ +
+
+ui_color = '#1CB1C2'[source]
+
+ +
+
+ui_fgcolor = '#fff'[source]
+
+ +
+ +
+ +
+
+execute(context)[source]
+

Derive when creating an operator.

+

Context is the same dictionary used as when rendering jinja templates.

+

Refer to get_template_context for more context.

+
+
+
+ +
+
+on_kill()[source]
+

Override this method to clean up subprocesses when a task instance gets killed.

+

Any use of the threading, subprocess or multiprocessing module within an +operator needs to be cleaned up, or it will leave ghost processes behind.

+
+ +
+
+execute_complete(context, event)[source]
+
+
+
+ +
+ +
+
+class airflow.providers.databricks.operators.databricks.DatabricksSubmitRunDeferrableOperator(*args, **kwargs)[source]
+

Bases: DatabricksSubmitRunOperator

+

Deferrable version of DatabricksSubmitRunOperator.

+
+
+execute(context)[source]
+

Derive when creating an operator.

+

Context is the same dictionary used as when rendering jinja templates.

+

Refer to get_template_context for more context.

+
+ +
+ +
+
+class airflow.providers.databricks.operators.databricks.DatabricksRunNowOperator(*, job_id=None, job_name=None, json=None, notebook_params=None, python_params=None, jar_params=None, spark_submit_params=None, python_named_params=None, idempotency_token=None, databricks_conn_id='databricks_default', polling_period_seconds=30, databricks_retry_limit=3, databricks_retry_delay=1, databricks_retry_args=None, do_xcom_push=True, wait_for_termination=True, deferrable=conf.getboolean('operators', 'default_deferrable', fallback=False), repair_run=False, cancel_previous_runs=False, **kwargs)[source]
+

Bases: airflow.models.BaseOperator

+

Runs an existing Spark job run to Databricks using the api/2.1/jobs/run-now API endpoint.

+

See: https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunNow

+

There are two ways to instantiate this operator.

+

In the first way, you can take the JSON payload that you typically use +to call the api/2.1/jobs/run-now endpoint and pass it directly +to our DatabricksRunNowOperator through the json parameter. +For example

+
json = {
+    "job_id": 42,
+    "notebook_params": {"dry-run": "true", "oldest-time-to-consider": "1457570074236"},
+}
+
+notebook_run = DatabricksRunNowOperator(task_id="notebook_run", json=json)
+
+
+

Another way to accomplish the same thing is to use the named parameters +of the DatabricksRunNowOperator directly. Note that there is exactly +one named parameter for each top level parameter in the run-now +endpoint. In this method, your code would look like this:

+
job_id = 42
+
+notebook_params = {"dry-run": "true", "oldest-time-to-consider": "1457570074236"}
+
+python_params = ["douglas adams", "42"]
+
+jar_params = ["douglas adams", "42"]
+
+spark_submit_params = ["--class", "org.apache.spark.examples.SparkPi"]
+
+notebook_run = DatabricksRunNowOperator(
+    job_id=job_id,
+    notebook_params=notebook_params,
+    python_params=python_params,
+    jar_params=jar_params,
+    spark_submit_params=spark_submit_params,
+)
+
+
+

In the case where both the json parameter AND the named parameters +are provided, they will be merged together. If there are conflicts during the merge, +the named parameters will take precedence and override the top level json keys.

+
+
Currently the named parameters that DatabricksRunNowOperator supports are
    +
  • job_id

  • +
  • job_name

  • +
  • json

  • +
  • notebook_params

  • +
  • python_params

  • +
  • python_named_parameters

  • +
  • jar_params

  • +
  • spark_submit_params

  • +
  • idempotency_token

  • +
  • repair_run

  • +
  • cancel_previous_runs

  • +
+
+
+
+
Parameters
+
    +
  • job_id (str | None) --

    the job_id of the existing Databricks job. +This field will be templated.

    + +

  • +
  • job_name (str | None) -- the name of the existing Databricks job. +It must exist only one job with the specified name. +job_id and job_name are mutually exclusive. +This field will be templated.

  • +
  • json (Any | None) --

    A JSON object containing API parameters which will be passed +directly to the api/2.1/jobs/run-now endpoint. The other named parameters +(i.e. notebook_params, spark_submit_params..) to this operator will +be merged with this json dictionary if they are provided. +If there are conflicts during the merge, the named parameters will +take precedence and override the top level json keys. (templated)

    + +

  • +
  • notebook_params (dict[str, str] | None) --

    A dict from keys to values for jobs with notebook task, +e.g. "notebook_params": {"name": "john doe", "age": "35"}. +The map is passed to the notebook and will be accessible through the +dbutils.widgets.get function. See Widgets for more information. +If not specified upon run-now, the triggered run will use the +job's base parameters. notebook_params cannot be +specified in conjunction with jar_params. The json representation +of this field (i.e. {"notebook_params":{"name":"john doe","age":"35"}}) +cannot exceed 10,000 bytes. +This field will be templated.

    + +

  • +
  • python_params (list[str] | None) --

    A list of parameters for jobs with python tasks, +e.g. "python_params": ["john doe", "35"]. +The parameters will be passed to python file as command line parameters. +If specified upon run-now, it would overwrite the parameters specified in job setting. +The json representation of this field (i.e. {"python_params":["john doe","35"]}) +cannot exceed 10,000 bytes. +This field will be templated.

    + +

  • +
  • python_named_params (dict[str, str] | None) --

    A list of named parameters for jobs with python wheel tasks, +e.g. "python_named_params": {"name": "john doe", "age": "35"}. +If specified upon run-now, it would overwrite the parameters specified in job setting. +This field will be templated.

    + +

  • +
  • jar_params (list[str] | None) --

    A list of parameters for jobs with JAR tasks, +e.g. "jar_params": ["john doe", "35"]. +The parameters will be passed to JAR file as command line parameters. +If specified upon run-now, it would overwrite the parameters specified in +job setting. +The json representation of this field (i.e. {"jar_params":["john doe","35"]}) +cannot exceed 10,000 bytes. +This field will be templated.

    + +

  • +
  • spark_submit_params (list[str] | None) --

    A list of parameters for jobs with spark submit task, +e.g. "spark_submit_params": ["--class", "org.apache.spark.examples.SparkPi"]. +The parameters will be passed to spark-submit script as command line parameters. +If specified upon run-now, it would overwrite the parameters specified +in job setting. +The json representation of this field cannot exceed 10,000 bytes. +This field will be templated.

    + +

  • +
  • idempotency_token (str | None) -- an optional token that can be used to guarantee the idempotency of job run +requests. If a run with the provided token already exists, the request does not create a new run but +returns the ID of the existing run instead. This token must have at most 64 characters.

  • +
  • databricks_conn_id (str) -- Reference to the Databricks connection. +By default and in the common case this will be databricks_default. To use +token based authentication, provide the key token in the extra field for the +connection and create the key host and leave the host field empty. (templated)

  • +
  • polling_period_seconds (int) -- Controls the rate which we poll for the result of +this run. By default, the operator will poll every 30 seconds.

  • +
  • databricks_retry_limit (int) -- Amount of times retry if the Databricks backend is +unreachable. Its value must be greater than or equal to 1.

  • +
  • databricks_retry_delay (int) -- Number of seconds to wait between retries (it +might be a floating point number).

  • +
  • databricks_retry_args (dict[Any, Any] | None) -- An optional dictionary with arguments passed to tenacity.Retrying class.

  • +
  • do_xcom_push (bool) -- Whether we should push run_id and run_page_url to xcom.

  • +
  • wait_for_termination (bool) -- if we should wait for termination of the job run. True by default.

  • +
  • deferrable (bool) -- Run operator in the deferrable mode.

  • +
  • repair_run (bool) -- Repair the databricks run in case of failure.

  • +
  • cancel_previous_runs (bool) -- Cancel all existing running jobs before submitting new one.

  • +
+
+
+
+
+template_fields: Sequence[str] = ('json', 'databricks_conn_id')[source]
+
+ +
+
+template_ext: Sequence[str] = ('.json-tpl',)[source]
+
+ +
+
+ui_color = '#1CB1C2'[source]
+
+ +
+
+ui_fgcolor = '#fff'[source]
+
+ +
+ +
+ +
+
+execute(context)[source]
+

Derive when creating an operator.

+

Context is the same dictionary used as when rendering jinja templates.

+

Refer to get_template_context for more context.

+
+
+
+ +
+
+execute_complete(context, event=None)[source]
+
+
+
+ +
+
+on_kill()[source]
+

Override this method to clean up subprocesses when a task instance gets killed.

+

Any use of the threading, subprocess or multiprocessing module within an +operator needs to be cleaned up, or it will leave ghost processes behind.

+
+
+
+ +
+ +
+
+class airflow.providers.databricks.operators.databricks.DatabricksRunNowDeferrableOperator(*args, **kwargs)[source]
+

Bases: DatabricksRunNowOperator

+

Deferrable version of DatabricksRunNowOperator.

+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/operators/databricks_repos/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/operators/databricks_repos/index.html new file mode 100644 index 00000000000..744bca248ec --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/operators/databricks_repos/index.html @@ -0,0 +1,1071 @@ + + + + + + + + + + + + airflow.providers.databricks.operators.databricks_repos — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.databricks.operators.databricks_repos

+

This module contains Databricks operators.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + + + + +

DatabricksReposCreateOperator

Creates, and optionally checks out, a Databricks Repo using the POST api/2.0/repos API endpoint.

DatabricksReposUpdateOperator

Updates specified repository to a given branch or tag using the PATCH api/2.0/repos API endpoint.

DatabricksReposDeleteOperator

Deletes specified repository using the DELETE api/2.0/repos API endpoint.

+
+
+class airflow.providers.databricks.operators.databricks_repos.DatabricksReposCreateOperator(*, git_url, git_provider=None, branch=None, tag=None, repo_path=None, ignore_existing_repo=False, databricks_conn_id='databricks_default', databricks_retry_limit=3, databricks_retry_delay=1, **kwargs)[source]
+

Bases: airflow.models.BaseOperator

+

Creates, and optionally checks out, a Databricks Repo using the POST api/2.0/repos API endpoint.

+
+
+
+
Parameters
+
    +
  • git_url (str) -- Required HTTPS URL of a Git repository

  • +
  • git_provider (str | None) -- Optional name of Git provider. Must be provided if we can't guess its name from URL.

  • +
  • repo_path (str | None) -- optional path for a repository. Must be in the format /Repos/{folder}/{repo-name}. +If not specified, it will be created in the user's directory.

  • +
  • branch (str | None) -- optional name of branch to check out.

  • +
  • tag (str | None) -- optional name of tag to checkout.

  • +
  • ignore_existing_repo (bool) -- don't throw exception if repository with given path already exists.

  • +
  • databricks_conn_id (str) -- Reference to the Databricks connection. +By default and in the common case this will be databricks_default. To use +token based authentication, provide the key token in the extra field for the +connection and create the key host and leave the host field empty. (templated)

  • +
  • databricks_retry_limit (int) -- Amount of times retry if the Databricks backend is +unreachable. Its value must be greater than or equal to 1.

  • +
  • databricks_retry_delay (int) -- Number of seconds to wait between retries (it +might be a floating point number).

  • +
+
+
+
+
+template_fields: Sequence[str] = ('repo_path', 'tag', 'branch', 'databricks_conn_id')[source]
+
+ +
+
+__git_providers__[source]
+
+ +
+
+__aws_code_commit_regexp__[source]
+
+ +
+
+__repos_path_regexp__[source]
+
+ +
+
+static __detect_repo_provider__(url)[source]
+
+ +
+
+execute(context)[source]
+

Create a Databricks Repo.

+
+
Parameters
+

context (airflow.utils.context.Context) -- context

+
+
Returns
+

Repo ID

+
+
+
+ +
+ +
+
+class airflow.providers.databricks.operators.databricks_repos.DatabricksReposUpdateOperator(*, branch=None, tag=None, repo_id=None, repo_path=None, databricks_conn_id='databricks_default', databricks_retry_limit=3, databricks_retry_delay=1, **kwargs)[source]
+

Bases: airflow.models.BaseOperator

+

Updates specified repository to a given branch or tag using the PATCH api/2.0/repos API endpoint.

+

See: https://docs.databricks.com/dev-tools/api/latest/repos.html#operation/update-repo

+
+
Parameters
+
    +
  • branch (str | None) -- optional name of branch to update to. Should be specified if tag is omitted

  • +
  • tag (str | None) -- optional name of tag to update to. Should be specified if branch is omitted

  • +
  • repo_id (str | None) -- optional ID of existing repository. Should be specified if repo_path is omitted

  • +
  • repo_path (str | None) -- optional path of existing repository. Should be specified if repo_id is omitted

  • +
  • databricks_conn_id (str) -- Reference to the Databricks connection. +By default and in the common case this will be databricks_default. To use +token based authentication, provide the key token in the extra field for the +connection and create the key host and leave the host field empty. (templated)

  • +
  • databricks_retry_limit (int) -- Amount of times retry if the Databricks backend is +unreachable. Its value must be greater than or equal to 1.

  • +
  • databricks_retry_delay (int) -- Number of seconds to wait between retries (it +might be a floating point number).

  • +
+
+
+
+
+template_fields: Sequence[str] = ('repo_path', 'tag', 'branch', 'databricks_conn_id')[source]
+
+ +
+
+execute(context)[source]
+

Derive when creating an operator.

+

Context is the same dictionary used as when rendering jinja templates.

+

Refer to get_template_context for more context.

+
+
+
+ +
+ +
+
+class airflow.providers.databricks.operators.databricks_repos.DatabricksReposDeleteOperator(*, repo_id=None, repo_path=None, databricks_conn_id='databricks_default', databricks_retry_limit=3, databricks_retry_delay=1, **kwargs)[source]
+

Bases: airflow.models.BaseOperator

+

Deletes specified repository using the DELETE api/2.0/repos API endpoint.

+

See: https://docs.databricks.com/dev-tools/api/latest/repos.html#operation/delete-repo

+
+
Parameters
+
    +
  • repo_id (str | None) -- optional ID of existing repository. Should be specified if repo_path is omitted

  • +
  • repo_path (str | None) -- optional path of existing repository. Should be specified if repo_id is omitted

  • +
  • databricks_conn_id (str) -- Reference to the Databricks connection. +By default and in the common case this will be databricks_default. To use +token based authentication, provide the key token in the extra field for the +connection and create the key host and leave the host field empty. (templated)

  • +
  • databricks_retry_limit (int) -- Amount of times retry if the Databricks backend is +unreachable. Its value must be greater than or equal to 1.

  • +
  • databricks_retry_delay (int) -- Number of seconds to wait between retries (it +might be a floating point number).

  • +
+
+
+
+
+template_fields: Sequence[str] = ('repo_path', 'databricks_conn_id')[source]
+
+ +
+
+execute(context)[source]
+

Derive when creating an operator.

+

Context is the same dictionary used as when rendering jinja templates.

+

Refer to get_template_context for more context.

+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/operators/databricks_sql/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/operators/databricks_sql/index.html new file mode 100644 index 00000000000..102566c37f5 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/operators/databricks_sql/index.html @@ -0,0 +1,1072 @@ + + + + + + + + + + + + airflow.providers.databricks.operators.databricks_sql — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.databricks.operators.databricks_sql

+

This module contains Databricks operators.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + +

DatabricksSqlOperator

Executes SQL code in a Databricks SQL endpoint or a Databricks cluster.

DatabricksCopyIntoOperator

Executes COPY INTO command in a Databricks SQL endpoint or a Databricks cluster.

+
+
+

Attributes

+ ++++ + + + + + +

COPY_INTO_APPROVED_FORMATS

+
+
+class airflow.providers.databricks.operators.databricks_sql.DatabricksSqlOperator(*, databricks_conn_id=DatabricksSqlHook.default_conn_name, http_path=None, sql_endpoint_name=None, session_configuration=None, http_headers=None, catalog=None, schema=None, output_path=None, output_format='csv', csv_params=None, client_parameters=None, **kwargs)[source]
+

Bases: airflow.providers.common.sql.operators.sql.SQLExecuteQueryOperator

+

Executes SQL code in a Databricks SQL endpoint or a Databricks cluster.

+
+

See also

+

For more information on how to use this operator, take a look at the guide: +DatabricksSqlOperator

+
+
+
Parameters
+
    +
  • databricks_conn_id (str) -- Reference to +Databricks connection id (templated)

  • +
  • http_path (str | None) -- Optional string specifying HTTP path of Databricks SQL Endpoint or cluster. +If not specified, it should be either specified in the Databricks connection's extra parameters, +or sql_endpoint_name must be specified.

  • +
  • sql_endpoint_name (str | None) -- Optional name of Databricks SQL Endpoint. If not specified, http_path must +be provided as described above.

  • +
  • sql -- the SQL code to be executed as a single string, or +a list of str (sql statements), or a reference to a template file. (templated) +Template references are recognized by str ending in '.sql'

  • +
  • parameters -- (optional) the parameters to render the SQL query with.

  • +
  • session_configuration -- An optional dictionary of Spark session parameters. Defaults to None. +If not specified, it could be specified in the Databricks connection's extra parameters.

  • +
  • client_parameters (dict[str, Any] | None) -- Additional parameters internal to Databricks SQL Connector parameters

  • +
  • http_headers (list[tuple[str, str]] | None) -- An optional list of (k, v) pairs that will be set as HTTP headers on every request. +(templated)

  • +
  • catalog (str | None) -- An optional initial catalog to use. Requires DBR version 9.0+ (templated)

  • +
  • schema (str | None) -- An optional initial schema to use. Requires DBR version 9.0+ (templated)

  • +
  • output_path (str | None) -- optional string specifying the file to which write selected data. (templated)

  • +
  • output_format (str) -- format of output data if output_path` is specified. +Possible values are ``csv, json, jsonl. Default is csv.

  • +
  • csv_params (dict[str, Any] | None) -- parameters that will be passed to the csv.DictWriter class used to write CSV data.

  • +
+
+
+
+
+template_fields: Sequence[str][source]
+
+ +
+
+template_ext: Sequence[str] = ('.sql',)[source]
+
+ +
+
+template_fields_renderers[source]
+
+ +
+
+conn_id_field = 'databricks_conn_id'[source]
+
+ +
+
+get_db_hook()[source]
+

Get the database hook for the connection.

+
+
Returns
+

the database hook object.

+
+
Return type
+

airflow.providers.databricks.hooks.databricks_sql.DatabricksSqlHook

+
+
+
+ +
+ +
+
+airflow.providers.databricks.operators.databricks_sql.COPY_INTO_APPROVED_FORMATS = ['CSV', 'JSON', 'AVRO', 'ORC', 'PARQUET', 'TEXT', 'BINARYFILE'][source]
+
+ +
+
+class airflow.providers.databricks.operators.databricks_sql.DatabricksCopyIntoOperator(*, table_name, file_location, file_format, databricks_conn_id=DatabricksSqlHook.default_conn_name, http_path=None, sql_endpoint_name=None, session_configuration=None, http_headers=None, client_parameters=None, catalog=None, schema=None, files=None, pattern=None, expression_list=None, credential=None, storage_credential=None, encryption=None, format_options=None, force_copy=None, copy_options=None, validate=None, **kwargs)[source]
+

Bases: airflow.models.BaseOperator

+

Executes COPY INTO command in a Databricks SQL endpoint or a Databricks cluster.

+

COPY INTO command is constructed from individual pieces, that are described in +documentation.

+
+

See also

+

For more information on how to use this operator, take a look at the guide: +DatabricksCopyIntoOperator

+
+
+
Parameters
+
    +
  • table_name (str) -- Required name of the table. (templated)

  • +
  • file_location (str) -- Required location of files to import. (templated)

  • +
  • file_format (str) -- Required file format. Supported formats are +CSV, JSON, AVRO, ORC, PARQUET, TEXT, BINARYFILE.

  • +
  • databricks_conn_id (str) -- Reference to +Databricks connection id (templated)

  • +
  • http_path (str | None) -- Optional string specifying HTTP path of Databricks SQL Endpoint or cluster. +If not specified, it should be either specified in the Databricks connection's extra parameters, +or sql_endpoint_name must be specified.

  • +
  • sql_endpoint_name (str | None) -- Optional name of Databricks SQL Endpoint. +If not specified, http_path must be provided as described above.

  • +
  • session_configuration -- An optional dictionary of Spark session parameters. Defaults to None. +If not specified, it could be specified in the Databricks connection's extra parameters.

  • +
  • http_headers (list[tuple[str, str]] | None) -- An optional list of (k, v) pairs that will be set as HTTP headers on every request

  • +
  • catalog (str | None) -- An optional initial catalog to use. Requires DBR version 9.0+

  • +
  • schema (str | None) -- An optional initial schema to use. Requires DBR version 9.0+

  • +
  • client_parameters (dict[str, Any] | None) -- Additional parameters internal to Databricks SQL Connector parameters

  • +
  • files (list[str] | None) -- optional list of files to import. Can't be specified together with pattern. (templated)

  • +
  • pattern (str | None) -- optional regex string to match file names to import. +Can't be specified together with files.

  • +
  • expression_list (str | None) -- optional string that will be used in the SELECT expression.

  • +
  • credential (dict[str, str] | None) -- optional credential configuration for authentication against a source location.

  • +
  • storage_credential (str | None) -- optional Unity Catalog storage credential for destination.

  • +
  • encryption (dict[str, str] | None) -- optional encryption configuration for a specified location.

  • +
  • format_options (dict[str, str] | None) -- optional dictionary with options specific for a given file format.

  • +
  • force_copy (bool | None) -- optional bool to control forcing of data import +(could be also specified in copy_options).

  • +
  • validate (bool | int | None) -- optional configuration for schema & data validation. True forces validation +of all rows, integer number - validate only N first rows

  • +
  • copy_options (dict[str, str] | None) -- optional dictionary of copy options. Right now only force option is supported.

  • +
+
+
+
+
+template_fields: Sequence[str] = ('file_location', 'files', 'table_name', 'databricks_conn_id')[source]
+
+ +
+
+execute(context)[source]
+

Derive when creating an operator.

+

Context is the same dictionary used as when rendering jinja templates.

+

Refer to get_template_context for more context.

+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/operators/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/operators/index.html new file mode 100644 index 00000000000..a7a078d6336 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/operators/index.html @@ -0,0 +1,881 @@ + + + + + + + + + + + + airflow.providers.databricks.operators — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/sensors/databricks_partition/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/sensors/databricks_partition/index.html new file mode 100644 index 00000000000..c8b7107b3f0 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/sensors/databricks_partition/index.html @@ -0,0 +1,961 @@ + + + + + + + + + + + + airflow.providers.databricks.sensors.databricks_partition — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.databricks.sensors.databricks_partition

+

This module contains Databricks sensors.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

DatabricksPartitionSensor

Sensor to detect the presence of table partitions in Databricks.

+
+
+class airflow.providers.databricks.sensors.databricks_partition.DatabricksPartitionSensor(*, databricks_conn_id=DatabricksSqlHook.default_conn_name, http_path=None, sql_warehouse_name=None, session_configuration=None, http_headers=None, catalog='', schema='default', table_name, partitions, partition_operator='=', handler=fetch_all_handler, client_parameters=None, **kwargs)[source]
+

Bases: airflow.sensors.base.BaseSensorOperator

+

Sensor to detect the presence of table partitions in Databricks.

+
+
Parameters
+
    +
  • databricks_conn_id (str) -- Reference to Databricks +connection id (templated), defaults to +DatabricksSqlHook.default_conn_name.

  • +
  • sql_warehouse_name (str | None) -- Optional name of Databricks SQL warehouse. If not specified, http_path +must be provided as described below, defaults to None

  • +
  • http_path (str | None) -- Optional string specifying HTTP path of Databricks SQL warehouse or All Purpose cluster. +If not specified, it should be either specified in the Databricks connection's +extra parameters, or sql_warehouse_name must be specified.

  • +
  • session_configuration -- An optional dictionary of Spark session parameters. If not specified, +it could be specified in the Databricks connection's extra parameters, defaults to None

  • +
  • http_headers (list[tuple[str, str]] | None) -- An optional list of (k, v) pairs +that will be set as HTTP headers on every request. (templated).

  • +
  • catalog (str) -- An optional initial catalog to use. +Requires Databricks Runtime version 9.0+ (templated), defaults to ""

  • +
  • schema (str) -- An optional initial schema to use. +Requires Databricks Runtime version 9.0+ (templated), defaults to "default"

  • +
  • table_name (str) -- Name of the table to check partitions.

  • +
  • partitions (dict) -- Name of the partitions to check. +Example: {"date": "2023-01-03", "name": ["abc", "def"]}

  • +
  • partition_operator (str) -- Optional comparison operator for partitions, such as >=.

  • +
  • handler (Callable[[Any], Any]) -- Handler for DbApiHook.run() to return results, defaults to fetch_all_handler

  • +
  • client_parameters (dict[str, Any] | None) -- Additional parameters internal to Databricks SQL connector parameters.

  • +
+
+
+
+
+template_fields: Sequence[str] = ('databricks_conn_id', 'catalog', 'schema', 'table_name', 'partitions', 'http_headers')[source]
+
+ +
+
+template_ext: Sequence[str] = ('.sql',)[source]
+
+ +
+
+template_fields_renderers[source]
+
+ +
+
+poke(context)[source]
+

Check the table partitions and return the results.

+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/sensors/databricks_sql/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/sensors/databricks_sql/index.html new file mode 100644 index 00000000000..5f141a19179 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/sensors/databricks_sql/index.html @@ -0,0 +1,967 @@ + + + + + + + + + + + + airflow.providers.databricks.sensors.databricks_sql — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.databricks.sensors.databricks_sql

+

This module contains Databricks sensors.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

DatabricksSqlSensor

Sensor that runs a SQL query on Databricks.

+
+
+class airflow.providers.databricks.sensors.databricks_sql.DatabricksSqlSensor(*, databricks_conn_id=DatabricksSqlHook.default_conn_name, http_path=None, sql_warehouse_name=None, session_configuration=None, http_headers=None, catalog='', schema='default', sql, handler=fetch_all_handler, client_parameters=None, **kwargs)[source]
+

Bases: airflow.sensors.base.BaseSensorOperator

+

Sensor that runs a SQL query on Databricks.

+
+
Parameters
+
    +
  • databricks_conn_id (str) -- Reference to Databricks +connection id (templated), defaults to +DatabricksSqlHook.default_conn_name.

  • +
  • sql_warehouse_name (str | None) -- Optional name of Databricks SQL warehouse. If not specified, http_path +must be provided as described below, defaults to None

  • +
  • http_path (str | None) -- Optional string specifying HTTP path of Databricks SQL warehouse or All Purpose cluster. +If not specified, it should be either specified in the Databricks connection's +extra parameters, or sql_warehouse_name must be specified.

  • +
  • session_configuration -- An optional dictionary of Spark session parameters. If not specified, +it could be specified in the Databricks connection's extra parameters, defaults to None

  • +
  • http_headers (list[tuple[str, str]] | None) -- An optional list of (k, v) pairs +that will be set as HTTP headers on every request. (templated).

  • +
  • catalog (str) -- An optional initial catalog to use. +Requires Databricks Runtime version 9.0+ (templated), defaults to ""

  • +
  • schema (str) -- An optional initial schema to use. +Requires Databricks Runtime version 9.0+ (templated), defaults to "default"

  • +
  • sql (str | Iterable[str]) -- SQL statement to be executed.

  • +
  • handler (Callable[[Any], Any]) -- Handler for DbApiHook.run() to return results, defaults to fetch_all_handler

  • +
  • client_parameters (dict[str, Any] | None) -- Additional parameters internal to Databricks SQL connector parameters.

  • +
+
+
+
+
+template_fields: Sequence[str] = ('databricks_conn_id', 'sql', 'catalog', 'schema', 'http_headers')[source]
+
+ +
+
+template_ext: Sequence[str] = ('.sql',)[source]
+
+ +
+
+template_fields_renderers[source]
+
+ +
+
+hook()[source]
+

Creates and returns a DatabricksSqlHook object.

+
+
+
+ +
+
+poke(context)[source]
+

Sensor poke function to get and return results from the SQL sensor.

+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/sensors/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/sensors/index.html new file mode 100644 index 00000000000..34c9b8c0377 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/sensors/index.html @@ -0,0 +1,880 @@ + + + + + + + + + + + + airflow.providers.databricks.sensors — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/triggers/databricks/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/triggers/databricks/index.html new file mode 100644 index 00000000000..3c44bd0ea3e --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/triggers/databricks/index.html @@ -0,0 +1,950 @@ + + + + + + + + + + + + airflow.providers.databricks.triggers.databricks — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.databricks.triggers.databricks

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

DatabricksExecutionTrigger

The trigger handles the logic of async communication with DataBricks API.

+
+
+class airflow.providers.databricks.triggers.databricks.DatabricksExecutionTrigger(run_id, databricks_conn_id, polling_period_seconds=30, retry_limit=3, retry_delay=10, retry_args=None, run_page_url=None, repair_run=False)[source]
+

Bases: airflow.triggers.base.BaseTrigger

+

The trigger handles the logic of async communication with DataBricks API.

+
+
Parameters
+
    +
  • run_id (int) -- id of the run

  • +
  • databricks_conn_id (str) -- Reference to the Databricks connection.

  • +
  • polling_period_seconds (int) -- Controls the rate of the poll for the result of this run. +By default, the trigger will poll every 30 seconds.

  • +
  • retry_limit (int) -- The number of times to retry the connection in case of service outages.

  • +
  • retry_delay (int) -- The number of seconds to wait between retries.

  • +
  • retry_args (dict[Any, Any] | None) -- An optional dictionary with arguments passed to tenacity.Retrying class.

  • +
  • run_page_url (str | None) -- The run page url.

  • +
+
+
+
+
+serialize()[source]
+

Return the information needed to reconstruct this Trigger.

+
+
Returns
+

Tuple of (class path, keyword arguments needed to re-instantiate).

+
+
Return type
+

tuple[str, dict[str, Any]]

+
+
+
+ +
+
+async run()[source]
+

Run the trigger in an asynchronous context.

+

The trigger should yield an Event whenever it wants to fire off +an event, and return None if it is finished. Single-event triggers +should thus yield and then immediately return.

+

If it yields, it is likely that it will be resumed very quickly, +but it may not be (e.g. if the workload is being moved to another +triggerer process, or a multi-event trigger was being used for a +single-event task defer).

+

In either case, Trigger classes should assume they will be persisted, +and then rely on cleanup() being called when they are no longer needed.

+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/triggers/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/triggers/index.html new file mode 100644 index 00000000000..657cc39f0e8 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/triggers/index.html @@ -0,0 +1,879 @@ + + + + + + + + + + + + airflow.providers.databricks.triggers — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/utils/databricks/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/utils/databricks/index.html new file mode 100644 index 00000000000..a0a101e386e --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/utils/databricks/index.html @@ -0,0 +1,923 @@ + + + + + + + + + + + + airflow.providers.databricks.utils.databricks — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.databricks.utils.databricks

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + + + + +

normalise_json_content(content[, json_path])

Normalize content or all values of content if it is a dict to a string.

validate_trigger_event(event)

Validate correctness of the event received from DatabricksExecutionTrigger.

+
+
+airflow.providers.databricks.utils.databricks.normalise_json_content(content, json_path='json')[source]
+

Normalize content or all values of content if it is a dict to a string.

+

The function will throw if content contains non-string or non-numeric non-boolean +types. The reason why we have this function is because the self.json field +must be a dict with only string values. This is because render_template will +fail for numerical values.

+

The only one exception is when we have boolean values, they can not be converted +to string type because databricks does not understand 'True' or 'False' values.

+
+
+
+ +
+
+airflow.providers.databricks.utils.databricks.validate_trigger_event(event)[source]
+

Validate correctness of the event received from DatabricksExecutionTrigger.

+

See: DatabricksExecutionTrigger.

+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/utils/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/utils/index.html new file mode 100644 index 00000000000..1c156b017ab --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/airflow/providers/databricks/utils/index.html @@ -0,0 +1,879 @@ + + + + + + + + + + + + airflow.providers.databricks.utils — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/example_databricks/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/example_databricks/index.html new file mode 100644 index 00000000000..5872fae1398 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/example_databricks/index.html @@ -0,0 +1,911 @@ + + + + + + + + + + + + tests.system.providers.databricks.example_databricks — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

tests.system.providers.databricks.example_databricks

+

This is an example DAG which uses the DatabricksSubmitRunOperator. +In this example, we create two tasks which execute sequentially. +The first task is to run a notebook at the workspace path "/test" +and the second task is to run a JAR uploaded to DBFS. Both, +tasks use new clusters.

+

Because we have set a downstream dependency on the notebook task, +the spark jar task will NOT run until the notebook task completes +successfully.

+

The definition of a successful run is if the run has a result_state of "SUCCESS". +For more information about the state of a run refer to +https://docs.databricks.com/api/latest/jobs.html#runstate

+
+

Module Contents

+
+
+tests.system.providers.databricks.example_databricks.ENV_ID[source]
+
+ +
+
+tests.system.providers.databricks.example_databricks.DAG_ID = 'example_databricks_operator'[source]
+
+ +
+
+tests.system.providers.databricks.example_databricks.job[source]
+
+ +
+
+tests.system.providers.databricks.example_databricks.test_run[source]
+
+ +
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/example_databricks_repos/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/example_databricks_repos/index.html new file mode 100644 index 00000000000..f6c0d2552f2 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/example_databricks_repos/index.html @@ -0,0 +1,906 @@ + + + + + + + + + + + + tests.system.providers.databricks.example_databricks_repos — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

tests.system.providers.databricks.example_databricks_repos

+
+

Module Contents

+
+
+tests.system.providers.databricks.example_databricks_repos.default_args[source]
+
+ +
+
+tests.system.providers.databricks.example_databricks_repos.ENV_ID[source]
+
+ +
+
+tests.system.providers.databricks.example_databricks_repos.DAG_ID = 'example_databricks_repos_operator'[source]
+
+ +
+
+tests.system.providers.databricks.example_databricks_repos.repo_path = '/Repos/user@domain.com/demo-repo'[source]
+
+ +
+
+tests.system.providers.databricks.example_databricks_repos.test_run[source]
+
+ +
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/example_databricks_sensors/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/example_databricks_sensors/index.html new file mode 100644 index 00000000000..3dd37c982d0 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/example_databricks_sensors/index.html @@ -0,0 +1,900 @@ + + + + + + + + + + + + tests.system.providers.databricks.example_databricks_sensors — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

tests.system.providers.databricks.example_databricks_sensors

+
+

Module Contents

+
+
+tests.system.providers.databricks.example_databricks_sensors.ENV_ID[source]
+
+ +
+
+tests.system.providers.databricks.example_databricks_sensors.DAG_ID = 'example_databricks_sensor'[source]
+
+ +
+
+tests.system.providers.databricks.example_databricks_sensors.connection_id = 'databricks_default'[source]
+
+ +
+
+tests.system.providers.databricks.example_databricks_sensors.test_run[source]
+
+ +
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/example_databricks_sql/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/example_databricks_sql/index.html new file mode 100644 index 00000000000..c225acac667 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/example_databricks_sql/index.html @@ -0,0 +1,908 @@ + + + + + + + + + + + + tests.system.providers.databricks.example_databricks_sql — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

tests.system.providers.databricks.example_databricks_sql

+

This is an example DAG which uses the DatabricksSqlOperator +and DatabricksCopyIntoOperator. The first task creates the table +and inserts values into it. The second task uses DatabricksSqlOperator +to select the data. The third task selects the data and stores the +output of selected data in file path and format specified. The fourth +task runs the select SQL statement written in the test.sql file. The +final task using DatabricksCopyIntoOperator loads the data from the +file_location passed into Delta table.

+
+

Module Contents

+
+
+tests.system.providers.databricks.example_databricks_sql.ENV_ID[source]
+
+ +
+
+tests.system.providers.databricks.example_databricks_sql.DAG_ID = 'example_databricks_sql_operator'[source]
+
+ +
+
+tests.system.providers.databricks.example_databricks_sql.connection_id = 'my_connection'[source]
+
+ +
+
+tests.system.providers.databricks.example_databricks_sql.test_run[source]
+
+ +
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/index.html new file mode 100644 index 00000000000..0c3377edb88 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_api/tests/system/providers/databricks/index.html @@ -0,0 +1,880 @@ + + + + + + + + + + + + tests.system.providers.databricks — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks.html new file mode 100644 index 00000000000..122209fec56 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks.html @@ -0,0 +1,879 @@ + + + + + + + + + + + + airflow.providers.databricks — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.databricks

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+# NOTE! THIS FILE IS AUTOMATICALLY GENERATED AND WILL BE
+# OVERWRITTEN WHEN PREPARING DOCUMENTATION FOR THE PACKAGES.
+#
+# IF YOU WANT TO MODIFY THIS FILE, YOU SHOULD MODIFY THE TEMPLATE
+# `PROVIDER__INIT__PY_TEMPLATE.py.jinja2` IN the `dev/breeze/src/airflow_breeze/templates` DIRECTORY
+#
+from __future__ import annotations
+
+import packaging.version
+
+__all__ = ["__version__"]
+
+
[docs]__version__ = "6.3.0"
+ +try: + from airflow import __version__ as airflow_version +except ImportError: + from airflow.version import version as airflow_version + +if packaging.version.parse(packaging.version.parse(airflow_version).base_version) < packaging.version.parse( + "2.6.0" +): + raise RuntimeError( + f"The package `apache-airflow-providers-databricks:{__version__}` needs Apache Airflow 2.6.0+" + ) +
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/hooks/databricks.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/hooks/databricks.html new file mode 100644 index 00000000000..1fb5b0a7eea --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/hooks/databricks.html @@ -0,0 +1,1518 @@ + + + + + + + + + + + + airflow.providers.databricks.hooks.databricks — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.databricks.hooks.databricks

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""
+Databricks hook.
+
+This hook enable the submitting and running of jobs to the Databricks platform. Internally the
+operators talk to the
+``api/2.1/jobs/run-now``
+`endpoint <https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunNow>_`
+or the ``api/2.1/jobs/runs/submit``
+`endpoint <https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunsSubmit>`_.
+"""
+
+from __future__ import annotations
+
+import json
+from typing import Any
+
+from requests import exceptions as requests_exceptions
+
+from airflow.exceptions import AirflowException
+from airflow.providers.databricks.hooks.databricks_base import BaseDatabricksHook
+
+
[docs]GET_CLUSTER_ENDPOINT = ("GET", "api/2.0/clusters/get")
+
[docs]RESTART_CLUSTER_ENDPOINT = ("POST", "api/2.0/clusters/restart")
+
[docs]START_CLUSTER_ENDPOINT = ("POST", "api/2.0/clusters/start")
+
[docs]TERMINATE_CLUSTER_ENDPOINT = ("POST", "api/2.0/clusters/delete")
+ +
[docs]CREATE_ENDPOINT = ("POST", "api/2.1/jobs/create")
+
[docs]RESET_ENDPOINT = ("POST", "api/2.1/jobs/reset")
+
[docs]RUN_NOW_ENDPOINT = ("POST", "api/2.1/jobs/run-now")
+
[docs]SUBMIT_RUN_ENDPOINT = ("POST", "api/2.1/jobs/runs/submit")
+
[docs]GET_RUN_ENDPOINT = ("GET", "api/2.1/jobs/runs/get")
+
[docs]CANCEL_RUN_ENDPOINT = ("POST", "api/2.1/jobs/runs/cancel")
+
[docs]DELETE_RUN_ENDPOINT = ("POST", "api/2.1/jobs/runs/delete")
+
[docs]REPAIR_RUN_ENDPOINT = ("POST", "api/2.1/jobs/runs/repair")
+
[docs]OUTPUT_RUNS_JOB_ENDPOINT = ("GET", "api/2.1/jobs/runs/get-output")
+
[docs]CANCEL_ALL_RUNS_ENDPOINT = ("POST", "api/2.1/jobs/runs/cancel-all")
+ +
[docs]INSTALL_LIBS_ENDPOINT = ("POST", "api/2.0/libraries/install")
+
[docs]UNINSTALL_LIBS_ENDPOINT = ("POST", "api/2.0/libraries/uninstall")
+ +
[docs]LIST_JOBS_ENDPOINT = ("GET", "api/2.1/jobs/list")
+
[docs]LIST_PIPELINES_ENDPOINT = ("GET", "api/2.0/pipelines")
+ +
[docs]WORKSPACE_GET_STATUS_ENDPOINT = ("GET", "api/2.0/workspace/get-status")
+ +
[docs]SPARK_VERSIONS_ENDPOINT = ("GET", "api/2.0/clusters/spark-versions")
+ + +
[docs]class RunState: + """Utility class for the run state concept of Databricks runs.""" + +
[docs] RUN_LIFE_CYCLE_STATES = [ + "PENDING", + "RUNNING", + "TERMINATING", + "TERMINATED", + "SKIPPED", + "INTERNAL_ERROR", + "QUEUED", + ]
+ + def __init__( + self, life_cycle_state: str, result_state: str = "", state_message: str = "", *args, **kwargs + ) -> None: + if life_cycle_state not in self.RUN_LIFE_CYCLE_STATES: + raise AirflowException( + f"Unexpected life cycle state: {life_cycle_state}: If the state has " + "been introduced recently, please check the Databricks user " + "guide for troubleshooting information" + ) + + self.life_cycle_state = life_cycle_state + self.result_state = result_state + self.state_message = state_message + + @property +
[docs] def is_terminal(self) -> bool: + """True if the current state is a terminal state.""" + return self.life_cycle_state in ("TERMINATED", "SKIPPED", "INTERNAL_ERROR")
+ + @property +
[docs] def is_successful(self) -> bool: + """True if the result state is SUCCESS.""" + return self.result_state == "SUCCESS"
+ +
[docs] def __eq__(self, other: object) -> bool: + if not isinstance(other, RunState): + return NotImplemented + return ( + self.life_cycle_state == other.life_cycle_state + and self.result_state == other.result_state + and self.state_message == other.state_message + )
+ +
[docs] def __repr__(self) -> str: + return str(self.__dict__)
+ +
[docs] def to_json(self) -> str: + return json.dumps(self.__dict__)
+ + @classmethod +
[docs] def from_json(cls, data: str) -> RunState: + return RunState(**json.loads(data))
+ + +
[docs]class ClusterState: + """Utility class for the cluster state concept of Databricks cluster.""" + +
[docs] CLUSTER_LIFE_CYCLE_STATES = [ + "PENDING", + "RUNNING", + "RESTARTING", + "RESIZING", + "TERMINATING", + "TERMINATED", + "ERROR", + "UNKNOWN", + ]
+ + def __init__(self, state: str = "", state_message: str = "", *args, **kwargs) -> None: + if state not in self.CLUSTER_LIFE_CYCLE_STATES: + raise AirflowException( + f"Unexpected cluster life cycle state: {state}: If the state has " + "been introduced recently, please check the Databricks user " + "guide for troubleshooting information" + ) + + self.state = state + self.state_message = state_message + + @property +
[docs] def is_terminal(self) -> bool: + """True if the current state is a terminal state.""" + return self.state in ("TERMINATING", "TERMINATED", "ERROR", "UNKNOWN")
+ + @property +
[docs] def is_running(self) -> bool: + """True if the current state is running.""" + return self.state in ("RUNNING", "RESIZING")
+ +
[docs] def __eq__(self, other) -> bool: + return self.state == other.state and self.state_message == other.state_message
+ +
[docs] def __repr__(self) -> str: + return str(self.__dict__)
+ +
[docs] def to_json(self) -> str: + return json.dumps(self.__dict__)
+ + @classmethod +
[docs] def from_json(cls, data: str) -> ClusterState: + return ClusterState(**json.loads(data))
+ + +
[docs]class DatabricksHook(BaseDatabricksHook): + """ + Interact with Databricks. + + :param databricks_conn_id: Reference to the :ref:`Databricks connection <howto/connection:databricks>`. + :param timeout_seconds: The amount of time in seconds the requests library + will wait before timing-out. + :param retry_limit: The number of times to retry the connection in case of + service outages. + :param retry_delay: The number of seconds to wait between retries (it + might be a floating point number). + :param retry_args: An optional dictionary with arguments passed to ``tenacity.Retrying`` class. + """ + +
[docs] hook_name = "Databricks"
+ + def __init__( + self, + databricks_conn_id: str = BaseDatabricksHook.default_conn_name, + timeout_seconds: int = 180, + retry_limit: int = 3, + retry_delay: float = 1.0, + retry_args: dict[Any, Any] | None = None, + caller: str = "DatabricksHook", + ) -> None: + super().__init__(databricks_conn_id, timeout_seconds, retry_limit, retry_delay, retry_args, caller) + +
[docs] def create_job(self, json: dict) -> int: + """Call the ``api/2.1/jobs/create`` endpoint. + + :param json: The data used in the body of the request to the ``create`` endpoint. + :return: the job_id as an int + """ + response = self._do_api_call(CREATE_ENDPOINT, json) + return response["job_id"]
+ +
[docs] def reset_job(self, job_id: str, json: dict) -> None: + """Call the ``api/2.1/jobs/reset`` endpoint. + + :param json: The data used in the new_settings of the request to the ``reset`` endpoint. + """ + self._do_api_call(RESET_ENDPOINT, {"job_id": job_id, "new_settings": json})
+ +
[docs] def run_now(self, json: dict) -> int: + """ + Call the ``api/2.1/jobs/run-now`` endpoint. + + :param json: The data used in the body of the request to the ``run-now`` endpoint. + :return: the run_id as an int + """ + response = self._do_api_call(RUN_NOW_ENDPOINT, json) + return response["run_id"]
+ +
[docs] def submit_run(self, json: dict) -> int: + """ + Call the ``api/2.1/jobs/runs/submit`` endpoint. + + :param json: The data used in the body of the request to the ``submit`` endpoint. + :return: the run_id as an int + """ + response = self._do_api_call(SUBMIT_RUN_ENDPOINT, json) + return response["run_id"]
+ +
[docs] def list_jobs( + self, + limit: int = 25, + expand_tasks: bool = False, + job_name: str | None = None, + page_token: str | None = None, + ) -> list[dict[str, Any]]: + """ + List the jobs in the Databricks Job Service. + + :param limit: The limit/batch size used to retrieve jobs. + :param expand_tasks: Whether to include task and cluster details in the response. + :param job_name: Optional name of a job to search. + :param page_token: The optional page token pointing at the first first job to return. + :return: A list of jobs. + """ + has_more = True + all_jobs = [] + if page_token is None: + page_token = "" + + while has_more: + payload: dict[str, Any] = { + "limit": limit, + "expand_tasks": expand_tasks, + } + payload["page_token"] = page_token + if job_name: + payload["name"] = job_name + response = self._do_api_call(LIST_JOBS_ENDPOINT, payload) + jobs = response.get("jobs", []) + if job_name: + all_jobs += [j for j in jobs if j["settings"]["name"] == job_name] + else: + all_jobs += jobs + has_more = response.get("has_more", False) + if has_more: + page_token = response.get("next_page_token", "") + + return all_jobs
+ +
[docs] def find_job_id_by_name(self, job_name: str) -> int | None: + """ + Find job id by its name; if there are multiple jobs with the same name, raise AirflowException. + + :param job_name: The name of the job to look up. + :return: The job_id as an int or None if no job was found. + """ + matching_jobs = self.list_jobs(job_name=job_name) + + if len(matching_jobs) > 1: + raise AirflowException( + f"There are more than one job with name {job_name}. Please delete duplicated jobs first" + ) + + if not matching_jobs: + return None + else: + return matching_jobs[0]["job_id"]
+ +
[docs] def list_pipelines( + self, batch_size: int = 25, pipeline_name: str | None = None, notebook_path: str | None = None + ) -> list[dict[str, Any]]: + """ + List the pipelines in Databricks Delta Live Tables. + + :param batch_size: The limit/batch size used to retrieve pipelines. + :param pipeline_name: Optional name of a pipeline to search. Cannot be combined with path. + :param notebook_path: Optional notebook of a pipeline to search. Cannot be combined with name. + :return: A list of pipelines. + """ + has_more = True + next_token = None + all_pipelines = [] + filter = None + if pipeline_name and notebook_path: + raise AirflowException("Cannot combine pipeline_name and notebook_path in one request") + + if notebook_path: + filter = f"notebook='{notebook_path}'" + elif pipeline_name: + filter = f"name LIKE '{pipeline_name}'" + payload: dict[str, Any] = { + "max_results": batch_size, + } + if filter: + payload["filter"] = filter + + while has_more: + if next_token is not None: + payload = {**payload, "page_token": next_token} + response = self._do_api_call(LIST_PIPELINES_ENDPOINT, payload) + pipelines = response.get("statuses", []) + all_pipelines += pipelines + if "next_page_token" in response: + next_token = response["next_page_token"] + else: + has_more = False + + return all_pipelines
+ +
[docs] def find_pipeline_id_by_name(self, pipeline_name: str) -> str | None: + """ + Find pipeline id by its name; if multiple pipelines with the same name, raise AirflowException. + + :param pipeline_name: The name of the pipeline to look up. + :return: The pipeline_id as a GUID string or None if no pipeline was found. + """ + matching_pipelines = self.list_pipelines(pipeline_name=pipeline_name) + + if len(matching_pipelines) > 1: + raise AirflowException( + f"There are more than one pipelines with name {pipeline_name}. " + "Please delete duplicated pipelines first" + ) + + if not pipeline_name or len(matching_pipelines) == 0: + return None + else: + return matching_pipelines[0]["pipeline_id"]
+ +
[docs] def get_run_page_url(self, run_id: int) -> str: + """ + Retrieve run_page_url. + + :param run_id: id of the run + :return: URL of the run page + """ + json = {"run_id": run_id} + response = self._do_api_call(GET_RUN_ENDPOINT, json) + return response["run_page_url"]
+ +
[docs] async def a_get_run_page_url(self, run_id: int) -> str: + """ + Async version of `get_run_page_url()`. + + :param run_id: id of the run + :return: URL of the run page + """ + json = {"run_id": run_id} + response = await self._a_do_api_call(GET_RUN_ENDPOINT, json) + return response["run_page_url"]
+ +
[docs] def get_job_id(self, run_id: int) -> int: + """ + Retrieve job_id from run_id. + + :param run_id: id of the run + :return: Job id for given Databricks run + """ + json = {"run_id": run_id} + response = self._do_api_call(GET_RUN_ENDPOINT, json) + return response["job_id"]
+ +
[docs] def get_run_state(self, run_id: int) -> RunState: + """ + Retrieve run state of the run. + + Please note that any Airflow tasks that call the ``get_run_state`` method will result in + failure unless you have enabled xcom pickling. This can be done using the following + environment variable: ``AIRFLOW__CORE__ENABLE_XCOM_PICKLING`` + + If you do not want to enable xcom pickling, use the ``get_run_state_str`` method to get + a string describing state, or ``get_run_state_lifecycle``, ``get_run_state_result``, or + ``get_run_state_message`` to get individual components of the run state. + + :param run_id: id of the run + :return: state of the run + """ + json = {"run_id": run_id} + response = self._do_api_call(GET_RUN_ENDPOINT, json) + state = response["state"] + return RunState(**state)
+ +
[docs] async def a_get_run_state(self, run_id: int) -> RunState: + """ + Async version of `get_run_state()`. + + :param run_id: id of the run + :return: state of the run + """ + json = {"run_id": run_id} + response = await self._a_do_api_call(GET_RUN_ENDPOINT, json) + state = response["state"] + return RunState(**state)
+ +
[docs] def get_run(self, run_id: int) -> dict[str, Any]: + """ + Retrieve run information. + + :param run_id: id of the run + :return: state of the run + """ + json = {"run_id": run_id} + response = self._do_api_call(GET_RUN_ENDPOINT, json) + return response
+ +
[docs] async def a_get_run(self, run_id: int) -> dict[str, Any]: + """ + Async version of `get_run`. + + :param run_id: id of the run + :return: state of the run + """ + json = {"run_id": run_id} + response = await self._a_do_api_call(GET_RUN_ENDPOINT, json) + return response
+ +
[docs] def get_run_state_str(self, run_id: int) -> str: + """ + Return the string representation of RunState. + + :param run_id: id of the run + :return: string describing run state + """ + state = self.get_run_state(run_id) + run_state_str = ( + f"State: {state.life_cycle_state}. Result: {state.result_state}. {state.state_message}" + ) + return run_state_str
+ +
[docs] def get_run_state_lifecycle(self, run_id: int) -> str: + """ + Return the lifecycle state of the run. + + :param run_id: id of the run + :return: string with lifecycle state + """ + return self.get_run_state(run_id).life_cycle_state
+ +
[docs] def get_run_state_result(self, run_id: int) -> str: + """ + Return the resulting state of the run. + + :param run_id: id of the run + :return: string with resulting state + """ + return self.get_run_state(run_id).result_state
+ +
[docs] def get_run_state_message(self, run_id: int) -> str: + """ + Return the state message for the run. + + :param run_id: id of the run + :return: string with state message + """ + return self.get_run_state(run_id).state_message
+ +
[docs] def get_run_output(self, run_id: int) -> dict: + """ + Retrieve run output of the run. + + :param run_id: id of the run + :return: output of the run + """ + json = {"run_id": run_id} + run_output = self._do_api_call(OUTPUT_RUNS_JOB_ENDPOINT, json) + return run_output
+ +
[docs] def cancel_run(self, run_id: int) -> None: + """ + Cancel the run. + + :param run_id: id of the run + """ + json = {"run_id": run_id} + self._do_api_call(CANCEL_RUN_ENDPOINT, json)
+ +
[docs] def cancel_all_runs(self, job_id: int) -> None: + """ + Cancel all active runs of a job asynchronously. + + :param job_id: The canonical identifier of the job to cancel all runs of + """ + json = {"job_id": job_id} + self._do_api_call(CANCEL_ALL_RUNS_ENDPOINT, json)
+ +
[docs] def delete_run(self, run_id: int) -> None: + """ + Delete a non-active run. + + :param run_id: id of the run + """ + json = {"run_id": run_id} + self._do_api_call(DELETE_RUN_ENDPOINT, json)
+ +
[docs] def repair_run(self, json: dict) -> int: + """ + Re-run one or more tasks. + + :param json: repair a job run. + """ + response = self._do_api_call(REPAIR_RUN_ENDPOINT, json) + return response["repair_id"]
+ +
[docs] def get_latest_repair_id(self, run_id: int) -> int | None: + """Get latest repair id if any exist for run_id else None.""" + json = {"run_id": run_id, "include_history": "true"} + response = self._do_api_call(GET_RUN_ENDPOINT, json) + repair_history = response["repair_history"] + if len(repair_history) == 1: + return None + else: + return repair_history[-1]["id"]
+ +
[docs] def get_cluster_state(self, cluster_id: str) -> ClusterState: + """ + Retrieve run state of the cluster. + + :param cluster_id: id of the cluster + :return: state of the cluster + """ + json = {"cluster_id": cluster_id} + response = self._do_api_call(GET_CLUSTER_ENDPOINT, json) + state = response["state"] + state_message = response["state_message"] + return ClusterState(state, state_message)
+ +
[docs] async def a_get_cluster_state(self, cluster_id: str) -> ClusterState: + """ + Async version of `get_cluster_state`. + + :param cluster_id: id of the cluster + :return: state of the cluster + """ + json = {"cluster_id": cluster_id} + response = await self._a_do_api_call(GET_CLUSTER_ENDPOINT, json) + state = response["state"] + state_message = response["state_message"] + return ClusterState(state, state_message)
+ +
[docs] def restart_cluster(self, json: dict) -> None: + """ + Restarts the cluster. + + :param json: json dictionary containing cluster specification. + """ + self._do_api_call(RESTART_CLUSTER_ENDPOINT, json)
+ +
[docs] def start_cluster(self, json: dict) -> None: + """ + Start the cluster. + + :param json: json dictionary containing cluster specification. + """ + self._do_api_call(START_CLUSTER_ENDPOINT, json)
+ +
[docs] def terminate_cluster(self, json: dict) -> None: + """ + Terminate the cluster. + + :param json: json dictionary containing cluster specification. + """ + self._do_api_call(TERMINATE_CLUSTER_ENDPOINT, json)
+ +
[docs] def install(self, json: dict) -> None: + """ + Install libraries on the cluster. + + Utility function to call the ``2.0/libraries/install`` endpoint. + + :param json: json dictionary containing cluster_id and an array of library + """ + self._do_api_call(INSTALL_LIBS_ENDPOINT, json)
+ +
[docs] def uninstall(self, json: dict) -> None: + """ + Uninstall libraries on the cluster. + + Utility function to call the ``2.0/libraries/uninstall`` endpoint. + + :param json: json dictionary containing cluster_id and an array of library + """ + self._do_api_call(UNINSTALL_LIBS_ENDPOINT, json)
+ +
[docs] def update_repo(self, repo_id: str, json: dict[str, Any]) -> dict: + """ + Update given Databricks Repos. + + :param repo_id: ID of Databricks Repos + :param json: payload + :return: metadata from update + """ + repos_endpoint = ("PATCH", f"api/2.0/repos/{repo_id}") + return self._do_api_call(repos_endpoint, json)
+ +
[docs] def delete_repo(self, repo_id: str): + """ + Delete given Databricks Repos. + + :param repo_id: ID of Databricks Repos + :return: + """ + repos_endpoint = ("DELETE", f"api/2.0/repos/{repo_id}") + self._do_api_call(repos_endpoint)
+ +
[docs] def create_repo(self, json: dict[str, Any]) -> dict: + """ + Create a Databricks Repos. + + :param json: payload + :return: + """ + repos_endpoint = ("POST", "api/2.0/repos") + return self._do_api_call(repos_endpoint, json)
+ +
[docs] def get_repo_by_path(self, path: str) -> str | None: + """ + Obtain Repos ID by path. + + :param path: path to a repository + :return: Repos ID if it exists, None if doesn't. + """ + try: + result = self._do_api_call(WORKSPACE_GET_STATUS_ENDPOINT, {"path": path}, wrap_http_errors=False) + if result.get("object_type", "") == "REPO": + return str(result["object_id"]) + except requests_exceptions.HTTPError as e: + if e.response.status_code != 404: + raise e + + return None
+ +
[docs] def update_job_permission(self, job_id: int, json: dict[str, Any]) -> dict: + """ + Update databricks job permission. + + :param job_id: job id + :param json: payload + :return: json containing permission specification + """ + return self._do_api_call(("PATCH", f"api/2.0/permissions/jobs/{job_id}"), json)
+ +
[docs] def test_connection(self) -> tuple[bool, str]: + """Test the Databricks connectivity from UI.""" + hook = DatabricksHook(databricks_conn_id=self.databricks_conn_id) + try: + hook._do_api_call(endpoint_info=SPARK_VERSIONS_ENDPOINT).get("versions") + status = True + message = "Connection successfully tested" + except Exception as e: + status = False + message = str(e) + + return status, message
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/hooks/databricks_base.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/hooks/databricks_base.html new file mode 100644 index 00000000000..d8794e2f1d2 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/hooks/databricks_base.html @@ -0,0 +1,1566 @@ + + + + + + + + + + + + airflow.providers.databricks.hooks.databricks_base — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.databricks.hooks.databricks_base

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""
+Databricks hook.
+
+This hook enable the submitting and running of jobs to the Databricks platform. Internally the
+operators talk to the ``api/2.0/jobs/runs/submit``
+`endpoint <https://docs.databricks.com/api/latest/jobs.html#runs-submit>`_.
+"""
+
+from __future__ import annotations
+
+import copy
+import platform
+import time
+from functools import cached_property
+from typing import TYPE_CHECKING, Any
+from urllib.parse import urlsplit
+
+import aiohttp
+import requests
+from requests import PreparedRequest, exceptions as requests_exceptions
+from requests.auth import AuthBase, HTTPBasicAuth
+from requests.exceptions import JSONDecodeError
+from tenacity import (
+    AsyncRetrying,
+    RetryError,
+    Retrying,
+    retry_if_exception,
+    stop_after_attempt,
+    wait_exponential,
+)
+
+from airflow import __version__
+from airflow.exceptions import AirflowException
+from airflow.hooks.base import BaseHook
+from airflow.providers_manager import ProvidersManager
+
+if TYPE_CHECKING:
+    from airflow.models import Connection
+
+# https://docs.microsoft.com/en-us/azure/databricks/dev-tools/api/latest/aad/service-prin-aad-token#--get-an-azure-active-directory-access-token
+# https://docs.microsoft.com/en-us/graph/deployments#app-registration-and-token-service-root-endpoints
+
[docs]AZURE_DEFAULT_AD_ENDPOINT = "https://login.microsoftonline.com"
+
[docs]AZURE_TOKEN_SERVICE_URL = "{}/{}/oauth2/token"
+# https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token +
[docs]AZURE_METADATA_SERVICE_TOKEN_URL = "http://169.254.169.254/metadata/identity/oauth2/token"
+
[docs]AZURE_METADATA_SERVICE_INSTANCE_URL = "http://169.254.169.254/metadata/instance"
+ +
[docs]TOKEN_REFRESH_LEAD_TIME = 120
+
[docs]AZURE_MANAGEMENT_ENDPOINT = "https://management.core.windows.net/"
+
[docs]DEFAULT_DATABRICKS_SCOPE = "2ff814a6-3304-4ab8-85cb-cd0e6f879c1d"
+
[docs]OIDC_TOKEN_SERVICE_URL = "{}/oidc/v1/token"
+ + +
[docs]class BaseDatabricksHook(BaseHook): + """ + Base for interaction with Databricks. + + :param databricks_conn_id: Reference to the :ref:`Databricks connection <howto/connection:databricks>`. + :param timeout_seconds: The amount of time in seconds the requests library + will wait before timing-out. + :param retry_limit: The number of times to retry the connection in case of + service outages. + :param retry_delay: The number of seconds to wait between retries (it + might be a floating point number). + :param retry_args: An optional dictionary with arguments passed to ``tenacity.Retrying`` class. + """ + +
[docs] conn_name_attr: str = "databricks_conn_id"
+
[docs] default_conn_name = "databricks_default"
+
[docs] conn_type = "databricks"
+ +
[docs] extra_parameters = [ + "token", + "host", + "use_azure_managed_identity", + "azure_ad_endpoint", + "azure_resource_id", + "azure_tenant_id", + "service_principal_oauth", + ]
+ + def __init__( + self, + databricks_conn_id: str = default_conn_name, + timeout_seconds: int = 180, + retry_limit: int = 3, + retry_delay: float = 1.0, + retry_args: dict[Any, Any] | None = None, + caller: str = "Unknown", + ) -> None: + super().__init__() + self.databricks_conn_id = databricks_conn_id + self.timeout_seconds = timeout_seconds + if retry_limit < 1: + raise ValueError("Retry limit must be greater than or equal to 1") + self.retry_limit = retry_limit + self.retry_delay = retry_delay + self.oauth_tokens: dict[str, dict] = {} + self.token_timeout_seconds = 10 + self.caller = caller + + def my_after_func(retry_state): + self._log_request_error(retry_state.attempt_number, retry_state.outcome) + + if retry_args: + self.retry_args = copy.copy(retry_args) + self.retry_args["retry"] = retry_if_exception(self._retryable_error) + self.retry_args["after"] = my_after_func + else: + self.retry_args = { + "stop": stop_after_attempt(self.retry_limit), + "wait": wait_exponential(min=self.retry_delay, max=(2**retry_limit)), + "retry": retry_if_exception(self._retryable_error), + "after": my_after_func, + } + + @cached_property +
[docs] def databricks_conn(self) -> Connection: + return self.get_connection(self.databricks_conn_id)
+ +
[docs] def get_conn(self) -> Connection: + return self.databricks_conn
+ + @cached_property +
[docs] def user_agent_header(self) -> dict[str, str]: + return {"user-agent": self.user_agent_value}
+ + @cached_property +
[docs] def user_agent_value(self) -> str: + manager = ProvidersManager() + package_name = manager.hooks[BaseDatabricksHook.conn_type].package_name # type: ignore[union-attr] + provider = manager.providers[package_name] + version = provider.version + python_version = platform.python_version() + system = platform.system().lower() + ua_string = ( + f"databricks-airflow/{version} _/0.0.0 python/{python_version} os/{system} " + f"airflow/{__version__} operator/{self.caller}" + ) + return ua_string
+ + @cached_property +
[docs] def host(self) -> str: + if "host" in self.databricks_conn.extra_dejson: + host = self._parse_host(self.databricks_conn.extra_dejson["host"]) + else: + host = self._parse_host(self.databricks_conn.host) + + return host
+ +
[docs] async def __aenter__(self): + self._session = aiohttp.ClientSession() + return self
+ +
[docs] async def __aexit__(self, *err): + await self._session.close() + self._session = None
+ + @staticmethod + def _parse_host(host: str) -> str: + """ + Parse host field data; this function is resistant to incorrect connection settings provided by users. + + For example -- when users supply ``https://xx.cloud.databricks.com`` as the + host, we must strip out the protocol to get the host.:: + + h = DatabricksHook() + assert h._parse_host('https://xx.cloud.databricks.com') == \ + 'xx.cloud.databricks.com' + + In the case where users supply the correct ``xx.cloud.databricks.com`` as the + host, this function is a no-op.:: + + assert h._parse_host('xx.cloud.databricks.com') == 'xx.cloud.databricks.com' + + """ + urlparse_host = urlsplit(host).hostname + if urlparse_host: + # In this case, host = https://xx.cloud.databricks.com + return urlparse_host + else: + # In this case, host = xx.cloud.databricks.com + return host + + def _get_retry_object(self) -> Retrying: + """ + Instantiate a retry object. + + :return: instance of Retrying class + """ + return Retrying(**self.retry_args) + + def _a_get_retry_object(self) -> AsyncRetrying: + """ + Instantiate an async retry object. + + :return: instance of AsyncRetrying class + """ + return AsyncRetrying(**self.retry_args) + + def _get_sp_token(self, resource: str) -> str: + """Get Service Principal token.""" + sp_token = self.oauth_tokens.get(resource) + if sp_token and self._is_oauth_token_valid(sp_token): + return sp_token["access_token"] + + self.log.info("Existing Service Principal token is expired, or going to expire soon. Refreshing...") + try: + for attempt in self._get_retry_object(): + with attempt: + resp = requests.post( + resource, + auth=HTTPBasicAuth(self.databricks_conn.login, self.databricks_conn.password), + data="grant_type=client_credentials&scope=all-apis", + headers={ + **self.user_agent_header, + "Content-Type": "application/x-www-form-urlencoded", + }, + timeout=self.token_timeout_seconds, + ) + + resp.raise_for_status() + jsn = resp.json() + jsn["expires_on"] = int(time.time() + jsn["expires_in"]) + + self._is_oauth_token_valid(jsn) + self.oauth_tokens[resource] = jsn + break + except RetryError: + raise AirflowException(f"API requests to Databricks failed {self.retry_limit} times. Giving up.") + except requests_exceptions.HTTPError as e: + msg = f"Response: {e.response.content.decode()}, Status Code: {e.response.status_code}" + raise AirflowException(msg) + + return jsn["access_token"] + + async def _a_get_sp_token(self, resource: str) -> str: + """Async version of `_get_sp_token()`.""" + sp_token = self.oauth_tokens.get(resource) + if sp_token and self._is_oauth_token_valid(sp_token): + return sp_token["access_token"] + + self.log.info("Existing Service Principal token is expired, or going to expire soon. Refreshing...") + try: + async for attempt in self._a_get_retry_object(): + with attempt: + async with self._session.post( + resource, + auth=aiohttp.BasicAuth(self.databricks_conn.login, self.databricks_conn.password), + data="grant_type=client_credentials&scope=all-apis", + headers={ + **self.user_agent_header, + "Content-Type": "application/x-www-form-urlencoded", + }, + timeout=self.token_timeout_seconds, + ) as resp: + resp.raise_for_status() + jsn = await resp.json() + jsn["expires_on"] = int(time.time() + jsn["expires_in"]) + + self._is_oauth_token_valid(jsn) + self.oauth_tokens[resource] = jsn + break + except RetryError: + raise AirflowException(f"API requests to Databricks failed {self.retry_limit} times. Giving up.") + except requests_exceptions.HTTPError as e: + msg = f"Response: {e.response.content.decode()}, Status Code: {e.response.status_code}" + raise AirflowException(msg) + + return jsn["access_token"] + + def _get_aad_token(self, resource: str) -> str: + """ + Get AAD token for given resource. + + Supports managed identity or service principal auth. + :param resource: resource to issue token to + :return: AAD token, or raise an exception + """ + aad_token = self.oauth_tokens.get(resource) + if aad_token and self._is_oauth_token_valid(aad_token): + return aad_token["access_token"] + + self.log.info("Existing AAD token is expired, or going to expire soon. Refreshing...") + try: + for attempt in self._get_retry_object(): + with attempt: + if self.databricks_conn.extra_dejson.get("use_azure_managed_identity", False): + params = { + "api-version": "2018-02-01", + "resource": resource, + } + resp = requests.get( + AZURE_METADATA_SERVICE_TOKEN_URL, + params=params, + headers={**self.user_agent_header, "Metadata": "true"}, + timeout=self.token_timeout_seconds, + ) + else: + tenant_id = self.databricks_conn.extra_dejson["azure_tenant_id"] + data = { + "grant_type": "client_credentials", + "client_id": self.databricks_conn.login, + "resource": resource, + "client_secret": self.databricks_conn.password, + } + azure_ad_endpoint = self.databricks_conn.extra_dejson.get( + "azure_ad_endpoint", AZURE_DEFAULT_AD_ENDPOINT + ) + resp = requests.post( + AZURE_TOKEN_SERVICE_URL.format(azure_ad_endpoint, tenant_id), + data=data, + headers={ + **self.user_agent_header, + "Content-Type": "application/x-www-form-urlencoded", + }, + timeout=self.token_timeout_seconds, + ) + + resp.raise_for_status() + jsn = resp.json() + + self._is_oauth_token_valid(jsn) + self.oauth_tokens[resource] = jsn + break + except RetryError: + raise AirflowException(f"API requests to Azure failed {self.retry_limit} times. Giving up.") + except requests_exceptions.HTTPError as e: + msg = f"Response: {e.response.content.decode()}, Status Code: {e.response.status_code}" + raise AirflowException(msg) + + return jsn["access_token"] + + async def _a_get_aad_token(self, resource: str) -> str: + """ + Async version of `_get_aad_token()`. + + :param resource: resource to issue token to + :return: AAD token, or raise an exception + """ + aad_token = self.oauth_tokens.get(resource) + if aad_token and self._is_oauth_token_valid(aad_token): + return aad_token["access_token"] + + self.log.info("Existing AAD token is expired, or going to expire soon. Refreshing...") + try: + async for attempt in self._a_get_retry_object(): + with attempt: + if self.databricks_conn.extra_dejson.get("use_azure_managed_identity", False): + params = { + "api-version": "2018-02-01", + "resource": resource, + } + async with self._session.get( + url=AZURE_METADATA_SERVICE_TOKEN_URL, + params=params, + headers={**self.user_agent_header, "Metadata": "true"}, + timeout=self.token_timeout_seconds, + ) as resp: + resp.raise_for_status() + jsn = await resp.json() + else: + tenant_id = self.databricks_conn.extra_dejson["azure_tenant_id"] + data = { + "grant_type": "client_credentials", + "client_id": self.databricks_conn.login, + "resource": resource, + "client_secret": self.databricks_conn.password, + } + azure_ad_endpoint = self.databricks_conn.extra_dejson.get( + "azure_ad_endpoint", AZURE_DEFAULT_AD_ENDPOINT + ) + async with self._session.post( + url=AZURE_TOKEN_SERVICE_URL.format(azure_ad_endpoint, tenant_id), + data=data, + headers={ + **self.user_agent_header, + "Content-Type": "application/x-www-form-urlencoded", + }, + timeout=self.token_timeout_seconds, + ) as resp: + resp.raise_for_status() + jsn = await resp.json() + + self._is_oauth_token_valid(jsn) + self.oauth_tokens[resource] = jsn + break + except RetryError: + raise AirflowException(f"API requests to Azure failed {self.retry_limit} times. Giving up.") + except aiohttp.ClientResponseError as err: + raise AirflowException(f"Response: {err.message}, Status Code: {err.status}") + + return jsn["access_token"] + + def _get_aad_headers(self) -> dict: + """ + Fill AAD headers if necessary (SPN is outside of the workspace). + + :return: dictionary with filled AAD headers + """ + headers = {} + if "azure_resource_id" in self.databricks_conn.extra_dejson: + mgmt_token = self._get_aad_token(AZURE_MANAGEMENT_ENDPOINT) + headers["X-Databricks-Azure-Workspace-Resource-Id"] = self.databricks_conn.extra_dejson[ + "azure_resource_id" + ] + headers["X-Databricks-Azure-SP-Management-Token"] = mgmt_token + return headers + + async def _a_get_aad_headers(self) -> dict: + """ + Async version of `_get_aad_headers()`. + + :return: dictionary with filled AAD headers + """ + headers = {} + if "azure_resource_id" in self.databricks_conn.extra_dejson: + mgmt_token = await self._a_get_aad_token(AZURE_MANAGEMENT_ENDPOINT) + headers["X-Databricks-Azure-Workspace-Resource-Id"] = self.databricks_conn.extra_dejson[ + "azure_resource_id" + ] + headers["X-Databricks-Azure-SP-Management-Token"] = mgmt_token + return headers + + @staticmethod + def _is_oauth_token_valid(token: dict, time_key="expires_on") -> bool: + """ + Check if an OAuth token is valid and hasn't expired yet. + + :param sp_token: dict with properties of OAuth token + :param time_key: name of the key that holds the time of expiration + :return: true if token is valid, false otherwise + """ + if "access_token" not in token or token.get("token_type", "") != "Bearer" or time_key not in token: + raise AirflowException(f"Can't get necessary data from OAuth token: {token}") + + return int(token[time_key]) > (int(time.time()) + TOKEN_REFRESH_LEAD_TIME) + + @staticmethod + def _check_azure_metadata_service() -> None: + """ + Check for Azure Metadata Service. + + https://docs.microsoft.com/en-us/azure/virtual-machines/linux/instance-metadata-service + """ + try: + jsn = requests.get( + AZURE_METADATA_SERVICE_INSTANCE_URL, + params={"api-version": "2021-02-01"}, + headers={"Metadata": "true"}, + timeout=2, + ).json() + if "compute" not in jsn or "azEnvironment" not in jsn["compute"]: + raise AirflowException( + f"Was able to fetch some metadata, but it doesn't look like Azure Metadata: {jsn}" + ) + except (requests_exceptions.RequestException, ValueError) as e: + raise AirflowException(f"Can't reach Azure Metadata Service: {e}") + + async def _a_check_azure_metadata_service(self): + """Async version of `_check_azure_metadata_service()`.""" + try: + async with self._session.get( + url=AZURE_METADATA_SERVICE_INSTANCE_URL, + params={"api-version": "2021-02-01"}, + headers={"Metadata": "true"}, + timeout=2, + ) as resp: + jsn = await resp.json() + if "compute" not in jsn or "azEnvironment" not in jsn["compute"]: + raise AirflowException( + f"Was able to fetch some metadata, but it doesn't look like Azure Metadata: {jsn}" + ) + except (requests_exceptions.RequestException, ValueError) as e: + raise AirflowException(f"Can't reach Azure Metadata Service: {e}") + + def _get_token(self, raise_error: bool = False) -> str | None: + if "token" in self.databricks_conn.extra_dejson: + self.log.info( + "Using token auth. For security reasons, please set token in Password field instead of extra" + ) + return self.databricks_conn.extra_dejson["token"] + elif not self.databricks_conn.login and self.databricks_conn.password: + self.log.info("Using token auth.") + return self.databricks_conn.password + elif "azure_tenant_id" in self.databricks_conn.extra_dejson: + if self.databricks_conn.login == "" or self.databricks_conn.password == "": + raise AirflowException("Azure SPN credentials aren't provided") + self.log.info("Using AAD Token for SPN.") + return self._get_aad_token(DEFAULT_DATABRICKS_SCOPE) + elif self.databricks_conn.extra_dejson.get("use_azure_managed_identity", False): + self.log.info("Using AAD Token for managed identity.") + self._check_azure_metadata_service() + return self._get_aad_token(DEFAULT_DATABRICKS_SCOPE) + elif self.databricks_conn.extra_dejson.get("service_principal_oauth", False): + if self.databricks_conn.login == "" or self.databricks_conn.password == "": + raise AirflowException("Service Principal credentials aren't provided") + self.log.info("Using Service Principal Token.") + return self._get_sp_token(OIDC_TOKEN_SERVICE_URL.format(self.databricks_conn.host)) + elif raise_error: + raise AirflowException("Token authentication isn't configured") + + return None + + async def _a_get_token(self, raise_error: bool = False) -> str | None: + if "token" in self.databricks_conn.extra_dejson: + self.log.info( + "Using token auth. For security reasons, please set token in Password field instead of extra" + ) + return self.databricks_conn.extra_dejson["token"] + elif not self.databricks_conn.login and self.databricks_conn.password: + self.log.info("Using token auth.") + return self.databricks_conn.password + elif "azure_tenant_id" in self.databricks_conn.extra_dejson: + if self.databricks_conn.login == "" or self.databricks_conn.password == "": + raise AirflowException("Azure SPN credentials aren't provided") + self.log.info("Using AAD Token for SPN.") + return await self._a_get_aad_token(DEFAULT_DATABRICKS_SCOPE) + elif self.databricks_conn.extra_dejson.get("use_azure_managed_identity", False): + self.log.info("Using AAD Token for managed identity.") + await self._a_check_azure_metadata_service() + return await self._a_get_aad_token(DEFAULT_DATABRICKS_SCOPE) + elif self.databricks_conn.extra_dejson.get("service_principal_oauth", False): + if self.databricks_conn.login == "" or self.databricks_conn.password == "": + raise AirflowException("Service Principal credentials aren't provided") + self.log.info("Using Service Principal Token.") + return await self._a_get_sp_token(OIDC_TOKEN_SERVICE_URL.format(self.databricks_conn.host)) + elif raise_error: + raise AirflowException("Token authentication isn't configured") + + return None + + def _log_request_error(self, attempt_num: int, error: str) -> None: + self.log.error("Attempt %s API Request to Databricks failed with reason: %s", attempt_num, error) + + def _do_api_call( + self, + endpoint_info: tuple[str, str], + json: dict[str, Any] | None = None, + wrap_http_errors: bool = True, + ): + """ + Perform an API call with retries. + + :param endpoint_info: Tuple of method and endpoint + :param json: Parameters for this API call. + :return: If the api call returns a OK status code, + this function returns the response in JSON. Otherwise, + we throw an AirflowException. + """ + method, endpoint = endpoint_info + + # TODO: get rid of explicit 'api/' in the endpoint specification + url = f"https://{self.host}/{endpoint}" + + aad_headers = self._get_aad_headers() + headers = {**self.user_agent_header, **aad_headers} + + auth: AuthBase + token = self._get_token() + if token: + auth = _TokenAuth(token) + else: + self.log.info("Using basic auth.") + auth = HTTPBasicAuth(self.databricks_conn.login, self.databricks_conn.password) + + request_func: Any + if method == "GET": + request_func = requests.get + elif method == "POST": + request_func = requests.post + elif method == "PATCH": + request_func = requests.patch + elif method == "DELETE": + request_func = requests.delete + else: + raise AirflowException("Unexpected HTTP Method: " + method) + + try: + for attempt in self._get_retry_object(): + with attempt: + response = request_func( + url, + json=json if method in ("POST", "PATCH") else None, + params=json if method == "GET" else None, + auth=auth, + headers=headers, + timeout=self.timeout_seconds, + ) + response.raise_for_status() + return response.json() + except RetryError: + raise AirflowException(f"API requests to Databricks failed {self.retry_limit} times. Giving up.") + except requests_exceptions.HTTPError as e: + if wrap_http_errors: + msg = f"Response: {e.response.content.decode()}, Status Code: {e.response.status_code}" + raise AirflowException(msg) + raise + + async def _a_do_api_call(self, endpoint_info: tuple[str, str], json: dict[str, Any] | None = None): + """ + Async version of `_do_api_call()`. + + :param endpoint_info: Tuple of method and endpoint + :param json: Parameters for this API call. + :return: If the api call returns a OK status code, + this function returns the response in JSON. Otherwise, throw an AirflowException. + """ + method, endpoint = endpoint_info + + url = f"https://{self.host}/{endpoint}" + + aad_headers = await self._a_get_aad_headers() + headers = {**self.user_agent_header, **aad_headers} + + auth: aiohttp.BasicAuth + token = await self._a_get_token() + if token: + auth = BearerAuth(token) + else: + self.log.info("Using basic auth.") + auth = aiohttp.BasicAuth(self.databricks_conn.login, self.databricks_conn.password) + + request_func: Any + if method == "GET": + request_func = self._session.get + elif method == "POST": + request_func = self._session.post + elif method == "PATCH": + request_func = self._session.patch + else: + raise AirflowException("Unexpected HTTP Method: " + method) + try: + async for attempt in self._a_get_retry_object(): + with attempt: + async with request_func( + url, + json=json, + auth=auth, + headers={**headers, **self.user_agent_header}, + timeout=self.timeout_seconds, + ) as response: + response.raise_for_status() + return await response.json() + except RetryError: + raise AirflowException(f"API requests to Databricks failed {self.retry_limit} times. Giving up.") + except aiohttp.ClientResponseError as err: + raise AirflowException(f"Response: {err.message}, Status Code: {err.status}") + + @staticmethod + def _get_error_code(exception: BaseException) -> str: + if isinstance(exception, requests_exceptions.HTTPError): + try: + jsn = exception.response.json() + return jsn.get("error_code", "") + except JSONDecodeError: + pass + + return "" + + @staticmethod + def _retryable_error(exception: BaseException) -> bool: + if isinstance(exception, requests_exceptions.RequestException): + if isinstance(exception, (requests_exceptions.ConnectionError, requests_exceptions.Timeout)) or ( + exception.response is not None + and ( + exception.response.status_code >= 500 + or exception.response.status_code == 429 + or ( + exception.response.status_code == 400 + and BaseDatabricksHook._get_error_code(exception) == "COULD_NOT_ACQUIRE_LOCK" + ) + ) + ): + return True + + if isinstance(exception, aiohttp.ClientResponseError): + if exception.status >= 500 or exception.status == 429: + return True + + return False
+ + +class _TokenAuth(AuthBase): + """ + Helper class for requests Auth field. + + AuthBase requires you to implement the ``__call__`` + magic function. + """ + + def __init__(self, token: str) -> None: + self.token = token + + def __call__(self, r: PreparedRequest) -> PreparedRequest: + r.headers["Authorization"] = "Bearer " + self.token + return r + + +
[docs]class BearerAuth(aiohttp.BasicAuth): + """aiohttp only ships BasicAuth, for Bearer auth we need a subclass of BasicAuth.""" + + def __new__(cls, token: str) -> BearerAuth: + return super().__new__(cls, token) # type: ignore + + def __init__(self, token: str) -> None: + self.token = token + +
[docs] def encode(self) -> str: + return f"Bearer {self.token}"
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/hooks/databricks_sql.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/hooks/databricks_sql.html new file mode 100644 index 00000000000..b909b042c8b --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/hooks/databricks_sql.html @@ -0,0 +1,1135 @@ + + + + + + + + + + + + airflow.providers.databricks.hooks.databricks_sql — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.databricks.hooks.databricks_sql

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import warnings
+from collections import namedtuple
+from contextlib import closing
+from copy import copy
+from typing import (
+    TYPE_CHECKING,
+    Any,
+    Callable,
+    Iterable,
+    List,
+    Mapping,
+    Sequence,
+    TypeVar,
+    cast,
+    overload,
+)
+
+from databricks import sql  # type: ignore[attr-defined]
+
+from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
+from airflow.providers.common.sql.hooks.sql import DbApiHook, return_single_query_results
+from airflow.providers.databricks.hooks.databricks_base import BaseDatabricksHook
+
+if TYPE_CHECKING:
+    from databricks.sql.client import Connection
+    from databricks.sql.types import Row
+
+
[docs]LIST_SQL_ENDPOINTS_ENDPOINT = ("GET", "api/2.0/sql/endpoints")
+ + +
[docs]T = TypeVar("T")
+ + +
[docs]class DatabricksSqlHook(BaseDatabricksHook, DbApiHook): + """Hook to interact with Databricks SQL. + + :param databricks_conn_id: Reference to the + :ref:`Databricks connection <howto/connection:databricks>`. + :param http_path: Optional string specifying HTTP path of Databricks SQL Endpoint or cluster. + If not specified, it should be either specified in the Databricks connection's extra parameters, + or ``sql_endpoint_name`` must be specified. + :param sql_endpoint_name: Optional name of Databricks SQL Endpoint. If not specified, ``http_path`` + must be provided as described above. + :param session_configuration: An optional dictionary of Spark session parameters. Defaults to None. + If not specified, it could be specified in the Databricks connection's extra parameters. + :param http_headers: An optional list of (k, v) pairs that will be set as HTTP headers + on every request + :param catalog: An optional initial catalog to use. Requires DBR version 9.0+ + :param schema: An optional initial schema to use. Requires DBR version 9.0+ + :param return_tuple: Return a ``namedtuple`` object instead of a ``databricks.sql.Row`` object. Default + to False. In a future release of the provider, this will become True by default. This parameter + ensures backward-compatibility during the transition phase to common tuple objects for all hooks based + on DbApiHook. This flag will also be removed in a future release. + :param kwargs: Additional parameters internal to Databricks SQL Connector parameters + """ + +
[docs] hook_name = "Databricks SQL"
+ _test_connection_sql = "select 42" + + def __init__( + self, + databricks_conn_id: str = BaseDatabricksHook.default_conn_name, + http_path: str | None = None, + sql_endpoint_name: str | None = None, + session_configuration: dict[str, str] | None = None, + http_headers: list[tuple[str, str]] | None = None, + catalog: str | None = None, + schema: str | None = None, + caller: str = "DatabricksSqlHook", + return_tuple: bool = False, + **kwargs, + ) -> None: + super().__init__(databricks_conn_id, caller=caller) + self._sql_conn = None + self._token: str | None = None + self._http_path = http_path + self._sql_endpoint_name = sql_endpoint_name + self.supports_autocommit = True + self.session_config = session_configuration + self.http_headers = http_headers + self.catalog = catalog + self.schema = schema + self.return_tuple = return_tuple + self.additional_params = kwargs + + if not self.return_tuple: + warnings.warn( + """Returning a raw `databricks.sql.Row` object is deprecated. A namedtuple will be + returned instead in a future release of the databricks provider. Set `return_tuple=True` to + enable this behavior.""", + AirflowProviderDeprecationWarning, + stacklevel=2, + ) + + def _get_extra_config(self) -> dict[str, Any | None]: + extra_params = copy(self.databricks_conn.extra_dejson) + for arg in ["http_path", "session_configuration", *self.extra_parameters]: + if arg in extra_params: + del extra_params[arg] + + return extra_params + + def _get_sql_endpoint_by_name(self, endpoint_name) -> dict[str, Any]: + result = self._do_api_call(LIST_SQL_ENDPOINTS_ENDPOINT) + if "endpoints" not in result: + raise AirflowException("Can't list Databricks SQL endpoints") + try: + endpoint = next(endpoint for endpoint in result["endpoints"] if endpoint["name"] == endpoint_name) + except StopIteration: + raise AirflowException(f"Can't find Databricks SQL endpoint with name '{endpoint_name}'") + else: + return endpoint + +
[docs] def get_conn(self) -> Connection: + """Return a Databricks SQL connection object.""" + if not self._http_path: + if self._sql_endpoint_name: + endpoint = self._get_sql_endpoint_by_name(self._sql_endpoint_name) + self._http_path = endpoint["odbc_params"]["path"] + elif "http_path" in self.databricks_conn.extra_dejson: + self._http_path = self.databricks_conn.extra_dejson["http_path"] + else: + raise AirflowException( + "http_path should be provided either explicitly, " + "or in extra parameter of Databricks connection, " + "or sql_endpoint_name should be specified" + ) + + requires_init = True + if not self._token: + self._token = self._get_token(raise_error=True) + else: + new_token = self._get_token(raise_error=True) + if new_token != self._token: + self._token = new_token + else: + requires_init = False + + if not self.session_config: + self.session_config = self.databricks_conn.extra_dejson.get("session_configuration") + + if not self._sql_conn or requires_init: + if self._sql_conn: # close already existing connection + self._sql_conn.close() + self._sql_conn = sql.connect( + self.host, + self._http_path, + self._token, + schema=self.schema, + catalog=self.catalog, + session_configuration=self.session_config, + http_headers=self.http_headers, + _user_agent_entry=self.user_agent_value, + **self._get_extra_config(), + **self.additional_params, + ) + return self._sql_conn
+ + @overload # type: ignore[override] +
[docs] def run( + self, + sql: str | Iterable[str], + autocommit: bool = ..., + parameters: Iterable | Mapping[str, Any] | None = ..., + handler: None = ..., + split_statements: bool = ..., + return_last: bool = ..., + ) -> None: ...
+ + @overload + def run( + self, + sql: str | Iterable[str], + autocommit: bool = ..., + parameters: Iterable | Mapping[str, Any] | None = ..., + handler: Callable[[Any], T] = ..., + split_statements: bool = ..., + return_last: bool = ..., + ) -> tuple | list[tuple] | list[list[tuple] | tuple] | None: ... + + def run( + self, + sql: str | Iterable[str], + autocommit: bool = False, + parameters: Iterable | Mapping[str, Any] | None = None, + handler: Callable[[Any], T] | None = None, + split_statements: bool = True, + return_last: bool = True, + ) -> tuple | list[tuple] | list[list[tuple] | tuple] | None: + """ + Run a command or a list of commands. + + Pass a list of SQL statements to the SQL parameter to get them to + execute sequentially. + + :param sql: the sql statement to be executed (str) or a list of + sql statements to execute + :param autocommit: What to set the connection's autocommit setting to + before executing the query. Note that currently there is no commit functionality + in Databricks SQL so this flag has no effect. + + :param parameters: The parameters to render the SQL query with. + :param handler: The result handler which is called with the result of each statement. + :param split_statements: Whether to split a single SQL string into statements and run separately + :param return_last: Whether to return result for only last statement or for all after split + :return: return only result of the LAST SQL expression if handler was provided unless return_last + is set to False. + """ + self.descriptions = [] + if isinstance(sql, str): + if split_statements: + sql_list = [self.strip_sql_string(s) for s in self.split_sql_string(sql)] + else: + sql_list = [self.strip_sql_string(sql)] + else: + sql_list = [self.strip_sql_string(s) for s in sql] + + if sql_list: + self.log.debug("Executing following statements against Databricks DB: %s", sql_list) + else: + raise ValueError("List of SQL statements is empty") + + conn = None + results = [] + for sql_statement in sql_list: + # when using AAD tokens, it could expire if previous query run longer than token lifetime + conn = self.get_conn() + with closing(conn.cursor()) as cur: + self.set_autocommit(conn, autocommit) + + with closing(conn.cursor()) as cur: + self._run_command(cur, sql_statement, parameters) # type: ignore[attr-defined] + if handler is not None: + raw_result = handler(cur) + if self.return_tuple: + result = self._make_common_data_structure(raw_result) + else: + # Returning raw result is deprecated, and do not comply with current common.sql interface + result = raw_result # type: ignore[assignment] + if return_single_query_results(sql, return_last, split_statements): + results = [result] + self.descriptions = [cur.description] + else: + results.append(result) + self.descriptions.append(cur.description) + if conn: + conn.close() + self._sql_conn = None + + if handler is None: + return None + if return_single_query_results(sql, return_last, split_statements): + return results[-1] + else: + return results + + def _make_common_data_structure(self, result: Sequence[Row] | Row) -> list[tuple] | tuple: + """Transform the databricks Row objects into namedtuple.""" + # Below ignored lines respect namedtuple docstring, but mypy do not support dynamically + # instantiated namedtuple, and will never do: https://github.com/python/mypy/issues/848 + if isinstance(result, list): + rows: list[Row] = result + if not rows: + return [] + rows_fields = tuple(rows[0].__fields__) + rows_object = namedtuple("Row", rows_fields, rename=True) # type: ignore + return cast(List[tuple], [rows_object(*row) for row in rows]) + else: + row: Row = result + row_fields = tuple(row.__fields__) + row_object = namedtuple("Row", row_fields, rename=True) # type: ignore + return cast(tuple, row_object(*row)) + +
[docs] def bulk_dump(self, table, tmp_file): + raise NotImplementedError()
+ +
[docs] def bulk_load(self, table, tmp_file): + raise NotImplementedError()
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/operators/databricks.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/operators/databricks.html new file mode 100644 index 00000000000..28e7dc2333e --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/operators/databricks.html @@ -0,0 +1,1725 @@ + + + + + + + + + + + + airflow.providers.databricks.operators.databricks — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.databricks.operators.databricks

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""This module contains Databricks operators."""
+
+from __future__ import annotations
+
+import time
+from functools import cached_property
+from logging import Logger
+from typing import TYPE_CHECKING, Any, Sequence
+
+from deprecated import deprecated
+
+from airflow.configuration import conf
+from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
+from airflow.models import BaseOperator, BaseOperatorLink, XCom
+from airflow.providers.databricks.hooks.databricks import DatabricksHook, RunState
+from airflow.providers.databricks.triggers.databricks import DatabricksExecutionTrigger
+from airflow.providers.databricks.utils.databricks import normalise_json_content, validate_trigger_event
+
+if TYPE_CHECKING:
+    from airflow.models.taskinstancekey import TaskInstanceKey
+    from airflow.utils.context import Context
+
+
[docs]DEFER_METHOD_NAME = "execute_complete"
+
[docs]XCOM_RUN_ID_KEY = "run_id"
+
[docs]XCOM_JOB_ID_KEY = "job_id"
+
[docs]XCOM_RUN_PAGE_URL_KEY = "run_page_url"
+ + +def _handle_databricks_operator_execution(operator, hook, log, context) -> None: + """ + Handle the Airflow + Databricks lifecycle logic for a Databricks operator. + + :param operator: Databricks operator being handled + :param context: Airflow context + """ + if operator.do_xcom_push and context is not None: + context["ti"].xcom_push(key=XCOM_RUN_ID_KEY, value=operator.run_id) + + log.info("Run submitted with run_id: %s", operator.run_id) + run_page_url = hook.get_run_page_url(operator.run_id) + if operator.do_xcom_push and context is not None: + context["ti"].xcom_push(key=XCOM_RUN_PAGE_URL_KEY, value=run_page_url) + + if operator.wait_for_termination: + while True: + run_info = hook.get_run(operator.run_id) + run_state = RunState(**run_info["state"]) + if run_state.is_terminal: + if run_state.is_successful: + log.info("%s completed successfully.", operator.task_id) + log.info("View run status, Spark UI, and logs at %s", run_page_url) + return + + if run_state.result_state == "FAILED": + task_run_id = None + if "tasks" in run_info: + for task in run_info["tasks"]: + if task.get("state", {}).get("result_state", "") == "FAILED": + task_run_id = task["run_id"] + if task_run_id is not None: + run_output = hook.get_run_output(task_run_id) + if "error" in run_output: + notebook_error = run_output["error"] + else: + notebook_error = run_state.state_message + else: + notebook_error = run_state.state_message + error_message = ( + f"{operator.task_id} failed with terminal state: {run_state} " + f"and with the error {notebook_error}" + ) + else: + error_message = ( + f"{operator.task_id} failed with terminal state: {run_state} " + f"and with the error {run_state.state_message}" + ) + + if isinstance(operator, DatabricksRunNowOperator) and operator.repair_run: + operator.repair_run = False + log.warning( + "%s but since repair run is set, repairing the run with all failed tasks", + error_message, + ) + + latest_repair_id = hook.get_latest_repair_id(operator.run_id) + repair_json = {"run_id": operator.run_id, "rerun_all_failed_tasks": True} + if latest_repair_id is not None: + repair_json["latest_repair_id"] = latest_repair_id + operator.json["latest_repair_id"] = hook.repair_run(operator, repair_json) + _handle_databricks_operator_execution(operator, hook, log, context) + raise AirflowException(error_message) + + log.info("%s in run state: %s", operator.task_id, run_state) + log.info("View run status, Spark UI, and logs at %s", run_page_url) + log.info("Sleeping for %s seconds.", operator.polling_period_seconds) + time.sleep(operator.polling_period_seconds) + + log.info("View run status, Spark UI, and logs at %s", run_page_url) + + +def _handle_deferrable_databricks_operator_execution(operator, hook, log, context) -> None: + """ + Handle the Airflow + Databricks lifecycle logic for deferrable Databricks operators. + + :param operator: Databricks async operator being handled + :param context: Airflow context + """ + job_id = hook.get_job_id(operator.run_id) + if operator.do_xcom_push and context is not None: + context["ti"].xcom_push(key=XCOM_JOB_ID_KEY, value=job_id) + if operator.do_xcom_push and context is not None: + context["ti"].xcom_push(key=XCOM_RUN_ID_KEY, value=operator.run_id) + log.info("Run submitted with run_id: %s", operator.run_id) + + run_page_url = hook.get_run_page_url(operator.run_id) + if operator.do_xcom_push and context is not None: + context["ti"].xcom_push(key=XCOM_RUN_PAGE_URL_KEY, value=run_page_url) + log.info("View run status, Spark UI, and logs at %s", run_page_url) + + if operator.wait_for_termination: + run_info = hook.get_run(operator.run_id) + run_state = RunState(**run_info["state"]) + if not run_state.is_terminal: + operator.defer( + trigger=DatabricksExecutionTrigger( + run_id=operator.run_id, + databricks_conn_id=operator.databricks_conn_id, + polling_period_seconds=operator.polling_period_seconds, + retry_limit=operator.databricks_retry_limit, + retry_delay=operator.databricks_retry_delay, + retry_args=operator.databricks_retry_args, + run_page_url=run_page_url, + repair_run=getattr(operator, "repair_run", False), + ), + method_name=DEFER_METHOD_NAME, + ) + else: + if run_state.is_successful: + log.info("%s completed successfully.", operator.task_id) + + +def _handle_deferrable_databricks_operator_completion(event: dict, log: Logger) -> None: + validate_trigger_event(event) + run_state = RunState.from_json(event["run_state"]) + run_page_url = event["run_page_url"] + log.info("View run status, Spark UI, and logs at %s", run_page_url) + + if run_state.is_successful: + log.info("Job run completed successfully.") + return + + error_message = f"Job run failed with terminal state: {run_state}" + if event["repair_run"]: + log.warning( + "%s but since repair run is set, repairing the run with all failed tasks", + error_message, + ) + return + raise AirflowException(error_message) + + + + + +
[docs]class DatabricksCreateJobsOperator(BaseOperator): + """Creates (or resets) a Databricks job using the API endpoint. + + .. seealso:: + https://docs.databricks.com/api/workspace/jobs/create + https://docs.databricks.com/api/workspace/jobs/reset + + :param json: A JSON object containing API parameters which will be passed + directly to the ``api/2.1/jobs/create`` endpoint. The other named parameters + (i.e. ``name``, ``tags``, ``tasks``, etc.) to this operator will + be merged with this json dictionary if they are provided. + If there are conflicts during the merge, the named parameters will + take precedence and override the top level json keys. (templated) + + .. seealso:: + For more information about templating see :ref:`concepts:jinja-templating`. + :param name: An optional name for the job. + :param tags: A map of tags associated with the job. + :param tasks: A list of task specifications to be executed by this job. + Array of objects (JobTaskSettings). + :param job_clusters: A list of job cluster specifications that can be shared and reused by + tasks of this job. Array of objects (JobCluster). + :param email_notifications: Object (JobEmailNotifications). + :param webhook_notifications: Object (WebhookNotifications). + :param timeout_seconds: An optional timeout applied to each run of this job. + :param schedule: Object (CronSchedule). + :param max_concurrent_runs: An optional maximum allowed number of concurrent runs of the job. + :param git_source: An optional specification for a remote repository containing the notebooks + used by this job's notebook tasks. Object (GitSource). + :param access_control_list: List of permissions to set on the job. Array of object + (AccessControlRequestForUser) or object (AccessControlRequestForGroup) or object + (AccessControlRequestForServicePrincipal). + + .. seealso:: + This will only be used on create. In order to reset ACL consider using the Databricks + UI. + :param databricks_conn_id: Reference to the + :ref:`Databricks connection <howto/connection:databricks>`. (templated) + :param polling_period_seconds: Controls the rate which we poll for the result of + this run. By default the operator will poll every 30 seconds. + :param databricks_retry_limit: Amount of times retry if the Databricks backend is + unreachable. Its value must be greater than or equal to 1. + :param databricks_retry_delay: Number of seconds to wait between retries (it + might be a floating point number). + :param databricks_retry_args: An optional dictionary with arguments passed to ``tenacity.Retrying`` class. + + """ + + # Used in airflow.models.BaseOperator +
[docs] template_fields: Sequence[str] = ("json", "databricks_conn_id")
+ # Databricks brand color (blue) under white text +
[docs] ui_color = "#1CB1C2"
+
[docs] ui_fgcolor = "#fff"
+ + def __init__( + self, + *, + json: Any | None = None, + name: str | None = None, + tags: dict[str, str] | None = None, + tasks: list[dict] | None = None, + job_clusters: list[dict] | None = None, + email_notifications: dict | None = None, + webhook_notifications: dict | None = None, + timeout_seconds: int | None = None, + schedule: dict | None = None, + max_concurrent_runs: int | None = None, + git_source: dict | None = None, + access_control_list: list[dict] | None = None, + databricks_conn_id: str = "databricks_default", + polling_period_seconds: int = 30, + databricks_retry_limit: int = 3, + databricks_retry_delay: int = 1, + databricks_retry_args: dict[Any, Any] | None = None, + **kwargs, + ) -> None: + """Create a new ``DatabricksCreateJobsOperator``.""" + super().__init__(**kwargs) + self.json = json or {} + self.databricks_conn_id = databricks_conn_id + self.polling_period_seconds = polling_period_seconds + self.databricks_retry_limit = databricks_retry_limit + self.databricks_retry_delay = databricks_retry_delay + self.databricks_retry_args = databricks_retry_args + if name is not None: + self.json["name"] = name + if tags is not None: + self.json["tags"] = tags + if tasks is not None: + self.json["tasks"] = tasks + if job_clusters is not None: + self.json["job_clusters"] = job_clusters + if email_notifications is not None: + self.json["email_notifications"] = email_notifications + if webhook_notifications is not None: + self.json["webhook_notifications"] = webhook_notifications + if timeout_seconds is not None: + self.json["timeout_seconds"] = timeout_seconds + if schedule is not None: + self.json["schedule"] = schedule + if max_concurrent_runs is not None: + self.json["max_concurrent_runs"] = max_concurrent_runs + if git_source is not None: + self.json["git_source"] = git_source + if access_control_list is not None: + self.json["access_control_list"] = access_control_list + if self.json: + self.json = normalise_json_content(self.json) + + @cached_property + def _hook(self): + return DatabricksHook( + self.databricks_conn_id, + retry_limit=self.databricks_retry_limit, + retry_delay=self.databricks_retry_delay, + retry_args=self.databricks_retry_args, + caller="DatabricksCreateJobsOperator", + ) + +
[docs] def execute(self, context: Context) -> int: + if "name" not in self.json: + raise AirflowException("Missing required parameter: name") + job_id = self._hook.find_job_id_by_name(self.json["name"]) + if job_id is None: + return self._hook.create_job(self.json) + self._hook.reset_job(str(job_id), self.json) + if (access_control_list := self.json.get("access_control_list")) is not None: + acl_json = {"access_control_list": access_control_list} + self._hook.update_job_permission(job_id, normalise_json_content(acl_json)) + + return job_id
+ + +
[docs]class DatabricksSubmitRunOperator(BaseOperator): + """ + Submits a Spark job run to Databricks using the api/2.1/jobs/runs/submit API endpoint. + + See: https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunsSubmit + + There are three ways to instantiate this operator. + + .. seealso:: + For more information on how to use this operator, take a look at the guide: + :ref:`howto/operator:DatabricksSubmitRunOperator` + + :param tasks: Array of Objects(RunSubmitTaskSettings) <= 100 items. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunsSubmit + :param json: A JSON object containing API parameters which will be passed + directly to the ``api/2.1/jobs/runs/submit`` endpoint. The other named parameters + (i.e. ``spark_jar_task``, ``notebook_task``..) to this operator will + be merged with this json dictionary if they are provided. + If there are conflicts during the merge, the named parameters will + take precedence and override the top level json keys. (templated) + + .. seealso:: + For more information about templating see :ref:`concepts:jinja-templating`. + https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunsSubmit + :param spark_jar_task: The main class and parameters for the JAR task. Note that + the actual JAR is specified in the ``libraries``. + *EITHER* ``spark_jar_task`` *OR* ``notebook_task`` *OR* ``spark_python_task`` + *OR* ``spark_submit_task`` *OR* ``pipeline_task`` *OR* ``dbt_task`` should be specified. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/2.0/jobs.html#jobssparkjartask + :param notebook_task: The notebook path and parameters for the notebook task. + *EITHER* ``spark_jar_task`` *OR* ``notebook_task`` *OR* ``spark_python_task`` + *OR* ``spark_submit_task`` *OR* ``pipeline_task`` *OR* ``dbt_task`` should be specified. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/2.0/jobs.html#jobsnotebooktask + :param spark_python_task: The python file path and parameters to run the python file with. + *EITHER* ``spark_jar_task`` *OR* ``notebook_task`` *OR* ``spark_python_task`` + *OR* ``spark_submit_task`` *OR* ``pipeline_task`` *OR* ``dbt_task`` should be specified. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/2.0/jobs.html#jobssparkpythontask + :param spark_submit_task: Parameters needed to run a spark-submit command. + *EITHER* ``spark_jar_task`` *OR* ``notebook_task`` *OR* ``spark_python_task`` + *OR* ``spark_submit_task`` *OR* ``pipeline_task`` *OR* ``dbt_task`` should be specified. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/2.0/jobs.html#jobssparksubmittask + :param pipeline_task: Parameters needed to execute a Delta Live Tables pipeline task. + The provided dictionary must contain at least ``pipeline_id`` field! + *EITHER* ``spark_jar_task`` *OR* ``notebook_task`` *OR* ``spark_python_task`` + *OR* ``spark_submit_task`` *OR* ``pipeline_task`` *OR* ``dbt_task`` should be specified. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/2.0/jobs.html#jobspipelinetask + :param dbt_task: Parameters needed to execute a dbt task. + The provided dictionary must contain at least the ``commands`` field and the + ``git_source`` parameter also needs to be set. + *EITHER* ``spark_jar_task`` *OR* ``notebook_task`` *OR* ``spark_python_task`` + *OR* ``spark_submit_task`` *OR* ``pipeline_task`` *OR* ``dbt_task`` should be specified. + This field will be templated. + + :param new_cluster: Specs for a new cluster on which this task will be run. + *EITHER* ``new_cluster`` *OR* ``existing_cluster_id`` should be specified + (except when ``pipeline_task`` is used). + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/2.0/jobs.html#jobsclusterspecnewcluster + :param existing_cluster_id: ID for existing cluster on which to run this task. + *EITHER* ``new_cluster`` *OR* ``existing_cluster_id`` should be specified + (except when ``pipeline_task`` is used). + This field will be templated. + :param libraries: Libraries which this run will use. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/2.0/jobs.html#managedlibrarieslibrary + :param run_name: The run name used for this task. + By default this will be set to the Airflow ``task_id``. This ``task_id`` is a + required parameter of the superclass ``BaseOperator``. + This field will be templated. + :param idempotency_token: an optional token that can be used to guarantee the idempotency of job run + requests. If a run with the provided token already exists, the request does not create a new run but + returns the ID of the existing run instead. This token must have at most 64 characters. + :param access_control_list: optional list of dictionaries representing Access Control List (ACL) for + a given job run. Each dictionary consists of following field - specific subject (``user_name`` for + users, or ``group_name`` for groups), and ``permission_level`` for that subject. See Jobs API + documentation for more details. + :param wait_for_termination: if we should wait for termination of the job run. ``True`` by default. + :param timeout_seconds: The timeout for this run. By default a value of 0 is used + which means to have no timeout. + This field will be templated. + :param databricks_conn_id: Reference to the :ref:`Databricks connection <howto/connection:databricks>`. + By default and in the common case this will be ``databricks_default``. To use + token based authentication, provide the key ``token`` in the extra field for the + connection and create the key ``host`` and leave the ``host`` field empty. (templated) + :param polling_period_seconds: Controls the rate which we poll for the result of + this run. By default the operator will poll every 30 seconds. + :param databricks_retry_limit: Amount of times retry if the Databricks backend is + unreachable. Its value must be greater than or equal to 1. + :param databricks_retry_delay: Number of seconds to wait between retries (it + might be a floating point number). + :param databricks_retry_args: An optional dictionary with arguments passed to ``tenacity.Retrying`` class. + :param do_xcom_push: Whether we should push run_id and run_page_url to xcom. + :param git_source: Optional specification of a remote git repository from which + supported task types are retrieved. + :param deferrable: Run operator in the deferrable mode. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunsSubmit + """ + + # Used in airflow.models.BaseOperator +
[docs] template_fields: Sequence[str] = ("json", "databricks_conn_id")
+
[docs] template_ext: Sequence[str] = (".json-tpl",)
+ # Databricks brand color (blue) under white text +
[docs] ui_color = "#1CB1C2"
+
[docs] ui_fgcolor = "#fff"
+ + + def __init__( + self, + *, + json: Any | None = None, + tasks: list[object] | None = None, + spark_jar_task: dict[str, str] | None = None, + notebook_task: dict[str, str] | None = None, + spark_python_task: dict[str, str | list[str]] | None = None, + spark_submit_task: dict[str, list[str]] | None = None, + pipeline_task: dict[str, str] | None = None, + dbt_task: dict[str, str | list[str]] | None = None, + new_cluster: dict[str, object] | None = None, + existing_cluster_id: str | None = None, + libraries: list[dict[str, Any]] | None = None, + run_name: str | None = None, + timeout_seconds: int | None = None, + databricks_conn_id: str = "databricks_default", + polling_period_seconds: int = 30, + databricks_retry_limit: int = 3, + databricks_retry_delay: int = 1, + databricks_retry_args: dict[Any, Any] | None = None, + do_xcom_push: bool = True, + idempotency_token: str | None = None, + access_control_list: list[dict[str, str]] | None = None, + wait_for_termination: bool = True, + git_source: dict[str, str] | None = None, + deferrable: bool = conf.getboolean("operators", "default_deferrable", fallback=False), + **kwargs, + ) -> None: + """Create a new ``DatabricksSubmitRunOperator``.""" + super().__init__(**kwargs) + self.json = json or {} + self.databricks_conn_id = databricks_conn_id + self.polling_period_seconds = polling_period_seconds + self.databricks_retry_limit = databricks_retry_limit + self.databricks_retry_delay = databricks_retry_delay + self.databricks_retry_args = databricks_retry_args + self.wait_for_termination = wait_for_termination + self.deferrable = deferrable + if tasks is not None: + self.json["tasks"] = tasks + if spark_jar_task is not None: + self.json["spark_jar_task"] = spark_jar_task + if notebook_task is not None: + self.json["notebook_task"] = notebook_task + if spark_python_task is not None: + self.json["spark_python_task"] = spark_python_task + if spark_submit_task is not None: + self.json["spark_submit_task"] = spark_submit_task + if pipeline_task is not None: + self.json["pipeline_task"] = pipeline_task + if dbt_task is not None: + self.json["dbt_task"] = dbt_task + if new_cluster is not None: + self.json["new_cluster"] = new_cluster + if existing_cluster_id is not None: + self.json["existing_cluster_id"] = existing_cluster_id + if libraries is not None: + self.json["libraries"] = libraries + if run_name is not None: + self.json["run_name"] = run_name + if timeout_seconds is not None: + self.json["timeout_seconds"] = timeout_seconds + if "run_name" not in self.json: + self.json["run_name"] = run_name or kwargs["task_id"] + if idempotency_token is not None: + self.json["idempotency_token"] = idempotency_token + if access_control_list is not None: + self.json["access_control_list"] = access_control_list + if git_source is not None: + self.json["git_source"] = git_source + + if "dbt_task" in self.json and "git_source" not in self.json: + raise AirflowException("git_source is required for dbt_task") + if pipeline_task is not None and "pipeline_id" in pipeline_task and "pipeline_name" in pipeline_task: + raise AirflowException("'pipeline_name' is not allowed in conjunction with 'pipeline_id'") + + # This variable will be used in case our task gets killed. + self.run_id: int | None = None + self.do_xcom_push = do_xcom_push + + @cached_property + def _hook(self): + return self._get_hook(caller="DatabricksSubmitRunOperator") + + def _get_hook(self, caller: str) -> DatabricksHook: + return DatabricksHook( + self.databricks_conn_id, + retry_limit=self.databricks_retry_limit, + retry_delay=self.databricks_retry_delay, + retry_args=self.databricks_retry_args, + caller=caller, + ) + +
[docs] def execute(self, context: Context): + if ( + "pipeline_task" in self.json + and self.json["pipeline_task"].get("pipeline_id") is None + and self.json["pipeline_task"].get("pipeline_name") + ): + # If pipeline_id is not provided, we need to fetch it from the pipeline_name + pipeline_name = self.json["pipeline_task"]["pipeline_name"] + self.json["pipeline_task"]["pipeline_id"] = self._hook.find_pipeline_id_by_name(pipeline_name) + del self.json["pipeline_task"]["pipeline_name"] + json_normalised = normalise_json_content(self.json) + self.run_id = self._hook.submit_run(json_normalised) + if self.deferrable: + _handle_deferrable_databricks_operator_execution(self, self._hook, self.log, context) + else: + _handle_databricks_operator_execution(self, self._hook, self.log, context)
+ +
[docs] def on_kill(self): + if self.run_id: + self._hook.cancel_run(self.run_id) + self.log.info( + "Task: %s with run_id: %s was requested to be cancelled.", self.task_id, self.run_id + ) + else: + self.log.error("Error: Task: %s with invalid run_id was requested to be cancelled.", self.task_id)
+ +
[docs] def execute_complete(self, context: dict | None, event: dict): + _handle_deferrable_databricks_operator_completion(event, self.log)
+ + +@deprecated( + reason=( + "`DatabricksSubmitRunDeferrableOperator` has been deprecated. " + "Please use `airflow.providers.databricks.operators.DatabricksSubmitRunOperator` " + "with `deferrable=True` instead." + ), + category=AirflowProviderDeprecationWarning, +) +
[docs]class DatabricksSubmitRunDeferrableOperator(DatabricksSubmitRunOperator): + """Deferrable version of ``DatabricksSubmitRunOperator``.""" + + def __init__(self, *args, **kwargs): + super().__init__(deferrable=True, *args, **kwargs) + +
[docs] def execute(self, context): + hook = self._get_hook(caller="DatabricksSubmitRunDeferrableOperator") + json_normalised = normalise_json_content(self.json) + self.run_id = hook.submit_run(json_normalised) + _handle_deferrable_databricks_operator_execution(self, hook, self.log, context)
+ + +
[docs]class DatabricksRunNowOperator(BaseOperator): + """ + Runs an existing Spark job run to Databricks using the api/2.1/jobs/run-now API endpoint. + + See: https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunNow + + There are two ways to instantiate this operator. + + In the first way, you can take the JSON payload that you typically use + to call the ``api/2.1/jobs/run-now`` endpoint and pass it directly + to our ``DatabricksRunNowOperator`` through the ``json`` parameter. + For example :: + + json = { + "job_id": 42, + "notebook_params": {"dry-run": "true", "oldest-time-to-consider": "1457570074236"}, + } + + notebook_run = DatabricksRunNowOperator(task_id="notebook_run", json=json) + + Another way to accomplish the same thing is to use the named parameters + of the ``DatabricksRunNowOperator`` directly. Note that there is exactly + one named parameter for each top level parameter in the ``run-now`` + endpoint. In this method, your code would look like this: :: + + job_id = 42 + + notebook_params = {"dry-run": "true", "oldest-time-to-consider": "1457570074236"} + + python_params = ["douglas adams", "42"] + + jar_params = ["douglas adams", "42"] + + spark_submit_params = ["--class", "org.apache.spark.examples.SparkPi"] + + notebook_run = DatabricksRunNowOperator( + job_id=job_id, + notebook_params=notebook_params, + python_params=python_params, + jar_params=jar_params, + spark_submit_params=spark_submit_params, + ) + + In the case where both the json parameter **AND** the named parameters + are provided, they will be merged together. If there are conflicts during the merge, + the named parameters will take precedence and override the top level ``json`` keys. + + Currently the named parameters that ``DatabricksRunNowOperator`` supports are + - ``job_id`` + - ``job_name`` + - ``json`` + - ``notebook_params`` + - ``python_params`` + - ``python_named_parameters`` + - ``jar_params`` + - ``spark_submit_params`` + - ``idempotency_token`` + - ``repair_run`` + - ``cancel_previous_runs`` + + :param job_id: the job_id of the existing Databricks job. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunNow + :param job_name: the name of the existing Databricks job. + It must exist only one job with the specified name. + ``job_id`` and ``job_name`` are mutually exclusive. + This field will be templated. + :param json: A JSON object containing API parameters which will be passed + directly to the ``api/2.1/jobs/run-now`` endpoint. The other named parameters + (i.e. ``notebook_params``, ``spark_submit_params``..) to this operator will + be merged with this json dictionary if they are provided. + If there are conflicts during the merge, the named parameters will + take precedence and override the top level json keys. (templated) + + .. seealso:: + For more information about templating see :ref:`concepts:jinja-templating`. + https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunNow + :param notebook_params: A dict from keys to values for jobs with notebook task, + e.g. "notebook_params": {"name": "john doe", "age": "35"}. + The map is passed to the notebook and will be accessible through the + dbutils.widgets.get function. See Widgets for more information. + If not specified upon run-now, the triggered run will use the + job's base parameters. notebook_params cannot be + specified in conjunction with jar_params. The json representation + of this field (i.e. {"notebook_params":{"name":"john doe","age":"35"}}) + cannot exceed 10,000 bytes. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/user-guide/notebooks/widgets.html + :param python_params: A list of parameters for jobs with python tasks, + e.g. "python_params": ["john doe", "35"]. + The parameters will be passed to python file as command line parameters. + If specified upon run-now, it would overwrite the parameters specified in job setting. + The json representation of this field (i.e. {"python_params":["john doe","35"]}) + cannot exceed 10,000 bytes. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunNow + :param python_named_params: A list of named parameters for jobs with python wheel tasks, + e.g. "python_named_params": {"name": "john doe", "age": "35"}. + If specified upon run-now, it would overwrite the parameters specified in job setting. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunNow + :param jar_params: A list of parameters for jobs with JAR tasks, + e.g. "jar_params": ["john doe", "35"]. + The parameters will be passed to JAR file as command line parameters. + If specified upon run-now, it would overwrite the parameters specified in + job setting. + The json representation of this field (i.e. {"jar_params":["john doe","35"]}) + cannot exceed 10,000 bytes. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunNow + :param spark_submit_params: A list of parameters for jobs with spark submit task, + e.g. "spark_submit_params": ["--class", "org.apache.spark.examples.SparkPi"]. + The parameters will be passed to spark-submit script as command line parameters. + If specified upon run-now, it would overwrite the parameters specified + in job setting. + The json representation of this field cannot exceed 10,000 bytes. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunNow + :param idempotency_token: an optional token that can be used to guarantee the idempotency of job run + requests. If a run with the provided token already exists, the request does not create a new run but + returns the ID of the existing run instead. This token must have at most 64 characters. + :param databricks_conn_id: Reference to the :ref:`Databricks connection <howto/connection:databricks>`. + By default and in the common case this will be ``databricks_default``. To use + token based authentication, provide the key ``token`` in the extra field for the + connection and create the key ``host`` and leave the ``host`` field empty. (templated) + :param polling_period_seconds: Controls the rate which we poll for the result of + this run. By default, the operator will poll every 30 seconds. + :param databricks_retry_limit: Amount of times retry if the Databricks backend is + unreachable. Its value must be greater than or equal to 1. + :param databricks_retry_delay: Number of seconds to wait between retries (it + might be a floating point number). + :param databricks_retry_args: An optional dictionary with arguments passed to ``tenacity.Retrying`` class. + :param do_xcom_push: Whether we should push run_id and run_page_url to xcom. + :param wait_for_termination: if we should wait for termination of the job run. ``True`` by default. + :param deferrable: Run operator in the deferrable mode. + :param repair_run: Repair the databricks run in case of failure. + :param cancel_previous_runs: Cancel all existing running jobs before submitting new one. + """ + + # Used in airflow.models.BaseOperator +
[docs] template_fields: Sequence[str] = ("json", "databricks_conn_id")
+
[docs] template_ext: Sequence[str] = (".json-tpl",)
+ # Databricks brand color (blue) under white text +
[docs] ui_color = "#1CB1C2"
+
[docs] ui_fgcolor = "#fff"
+ + + def __init__( + self, + *, + job_id: str | None = None, + job_name: str | None = None, + json: Any | None = None, + notebook_params: dict[str, str] | None = None, + python_params: list[str] | None = None, + jar_params: list[str] | None = None, + spark_submit_params: list[str] | None = None, + python_named_params: dict[str, str] | None = None, + idempotency_token: str | None = None, + databricks_conn_id: str = "databricks_default", + polling_period_seconds: int = 30, + databricks_retry_limit: int = 3, + databricks_retry_delay: int = 1, + databricks_retry_args: dict[Any, Any] | None = None, + do_xcom_push: bool = True, + wait_for_termination: bool = True, + deferrable: bool = conf.getboolean("operators", "default_deferrable", fallback=False), + repair_run: bool = False, + cancel_previous_runs: bool = False, + **kwargs, + ) -> None: + """Create a new ``DatabricksRunNowOperator``.""" + super().__init__(**kwargs) + self.json = json or {} + self.databricks_conn_id = databricks_conn_id + self.polling_period_seconds = polling_period_seconds + self.databricks_retry_limit = databricks_retry_limit + self.databricks_retry_delay = databricks_retry_delay + self.databricks_retry_args = databricks_retry_args + self.wait_for_termination = wait_for_termination + self.deferrable = deferrable + self.repair_run = repair_run + self.cancel_previous_runs = cancel_previous_runs + + if job_id is not None: + self.json["job_id"] = job_id + if job_name is not None: + self.json["job_name"] = job_name + if "job_id" in self.json and "job_name" in self.json: + raise AirflowException("Argument 'job_name' is not allowed with argument 'job_id'") + if notebook_params is not None: + self.json["notebook_params"] = notebook_params + if python_params is not None: + self.json["python_params"] = python_params + if python_named_params is not None: + self.json["python_named_params"] = python_named_params + if jar_params is not None: + self.json["jar_params"] = jar_params + if spark_submit_params is not None: + self.json["spark_submit_params"] = spark_submit_params + if idempotency_token is not None: + self.json["idempotency_token"] = idempotency_token + if self.json: + self.json = normalise_json_content(self.json) + # This variable will be used in case our task gets killed. + self.run_id: int | None = None + self.do_xcom_push = do_xcom_push + + @cached_property + def _hook(self): + return self._get_hook(caller="DatabricksRunNowOperator") + + def _get_hook(self, caller: str) -> DatabricksHook: + return DatabricksHook( + self.databricks_conn_id, + retry_limit=self.databricks_retry_limit, + retry_delay=self.databricks_retry_delay, + retry_args=self.databricks_retry_args, + caller=caller, + ) + +
[docs] def execute(self, context: Context): + hook = self._hook + if "job_name" in self.json: + job_id = hook.find_job_id_by_name(self.json["job_name"]) + if job_id is None: + raise AirflowException(f"Job ID for job name {self.json['job_name']} can not be found") + self.json["job_id"] = job_id + del self.json["job_name"] + + if self.cancel_previous_runs and self.json["job_id"] is not None: + hook.cancel_all_runs(self.json["job_id"]) + + self.run_id = hook.run_now(self.json) + if self.deferrable: + _handle_deferrable_databricks_operator_execution(self, hook, self.log, context) + else: + _handle_databricks_operator_execution(self, hook, self.log, context)
+ +
[docs] def execute_complete(self, context: Context, event: dict[str, Any] | None = None) -> None: + if event: + _handle_deferrable_databricks_operator_completion(event, self.log) + if event["repair_run"]: + self.repair_run = False + self.run_id = event["run_id"] + latest_repair_id = self._hook.get_latest_repair_id(self.run_id) + repair_json = {"run_id": self.run_id, "rerun_all_failed_tasks": True} + if latest_repair_id is not None: + repair_json["latest_repair_id"] = latest_repair_id + self.json["latest_repair_id"] = self._hook.repair_run(repair_json) + _handle_deferrable_databricks_operator_execution(self, self._hook, self.log, context)
+ +
[docs] def on_kill(self) -> None: + if self.run_id: + self._hook.cancel_run(self.run_id) + self.log.info( + "Task: %s with run_id: %s was requested to be cancelled.", self.task_id, self.run_id + ) + else: + self.log.error("Error: Task: %s with invalid run_id was requested to be cancelled.", self.task_id)
+ + +@deprecated( + reason=( + "`DatabricksRunNowDeferrableOperator` has been deprecated. " + "Please use `airflow.providers.databricks.operators.DatabricksRunNowOperator` " + "with `deferrable=True` instead." + ), + category=AirflowProviderDeprecationWarning, +) +
[docs]class DatabricksRunNowDeferrableOperator(DatabricksRunNowOperator): + """Deferrable version of ``DatabricksRunNowOperator``.""" + + def __init__(self, *args, **kwargs): + super().__init__(deferrable=True, *args, **kwargs)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/operators/databricks_repos.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/operators/databricks_repos.html new file mode 100644 index 00000000000..80933fd5d8e --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/operators/databricks_repos.html @@ -0,0 +1,1136 @@ + + + + + + + + + + + + airflow.providers.databricks.operators.databricks_repos — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.databricks.operators.databricks_repos

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""This module contains Databricks operators."""
+
+from __future__ import annotations
+
+import re
+from functools import cached_property
+from typing import TYPE_CHECKING, Sequence
+from urllib.parse import urlsplit
+
+from airflow.exceptions import AirflowException
+from airflow.models import BaseOperator
+from airflow.providers.databricks.hooks.databricks import DatabricksHook
+
+if TYPE_CHECKING:
+    from airflow.utils.context import Context
+
+
+
[docs]class DatabricksReposCreateOperator(BaseOperator): + """ + Creates, and optionally checks out, a Databricks Repo using the POST api/2.0/repos API endpoint. + + See: https://docs.databricks.com/dev-tools/api/latest/repos.html#operation/create-repo + + :param git_url: Required HTTPS URL of a Git repository + :param git_provider: Optional name of Git provider. Must be provided if we can't guess its name from URL. + :param repo_path: optional path for a repository. Must be in the format ``/Repos/{folder}/{repo-name}``. + If not specified, it will be created in the user's directory. + :param branch: optional name of branch to check out. + :param tag: optional name of tag to checkout. + :param ignore_existing_repo: don't throw exception if repository with given path already exists. + :param databricks_conn_id: Reference to the :ref:`Databricks connection <howto/connection:databricks>`. + By default and in the common case this will be ``databricks_default``. To use + token based authentication, provide the key ``token`` in the extra field for the + connection and create the key ``host`` and leave the ``host`` field empty. (templated) + :param databricks_retry_limit: Amount of times retry if the Databricks backend is + unreachable. Its value must be greater than or equal to 1. + :param databricks_retry_delay: Number of seconds to wait between retries (it + might be a floating point number). + """ + + # Used in airflow.models.BaseOperator +
[docs] template_fields: Sequence[str] = ("repo_path", "tag", "branch", "databricks_conn_id")
+ +
[docs] __git_providers__ = { + "github.com": "gitHub", + "dev.azure.com": "azureDevOpsServices", + "gitlab.com": "gitLab", + "bitbucket.org": "bitbucketCloud", + }
+
[docs] __aws_code_commit_regexp__ = re.compile(r"^git-codecommit\.[^.]+\.amazonaws.com$")
+
[docs] __repos_path_regexp__ = re.compile(r"/Repos/[^/]+/[^/]+/?$")
+ + def __init__( + self, + *, + git_url: str, + git_provider: str | None = None, + branch: str | None = None, + tag: str | None = None, + repo_path: str | None = None, + ignore_existing_repo: bool = False, + databricks_conn_id: str = "databricks_default", + databricks_retry_limit: int = 3, + databricks_retry_delay: int = 1, + **kwargs, + ) -> None: + """Create a new ``DatabricksReposCreateOperator``.""" + super().__init__(**kwargs) + self.databricks_conn_id = databricks_conn_id + self.databricks_retry_limit = databricks_retry_limit + self.databricks_retry_delay = databricks_retry_delay + self.git_url = git_url + self.ignore_existing_repo = ignore_existing_repo + if git_provider is None: + self.git_provider = self.__detect_repo_provider__(git_url) + if self.git_provider is None: + raise AirflowException( + f"git_provider isn't specified and couldn't be guessed for URL {git_url}" + ) + else: + self.git_provider = git_provider + self.repo_path = repo_path + if branch is not None and tag is not None: + raise AirflowException("Only one of branch or tag should be provided, but not both") + self.branch = branch + self.tag = tag + + @staticmethod +
[docs] def __detect_repo_provider__(url): + provider = None + try: + netloc = urlsplit(url).netloc.lower() + _, _, netloc = netloc.rpartition("@") + provider = DatabricksReposCreateOperator.__git_providers__.get(netloc) + if provider is None and DatabricksReposCreateOperator.__aws_code_commit_regexp__.match(netloc): + provider = "awsCodeCommit" + except ValueError: + pass + return provider
+ + @cached_property + def _hook(self) -> DatabricksHook: + return DatabricksHook( + self.databricks_conn_id, + retry_limit=self.databricks_retry_limit, + retry_delay=self.databricks_retry_delay, + caller="DatabricksReposCreateOperator", + ) + +
[docs] def execute(self, context: Context): + """ + Create a Databricks Repo. + + :param context: context + :return: Repo ID + """ + payload = { + "url": self.git_url, + "provider": self.git_provider, + } + if self.repo_path is not None: + if not self.__repos_path_regexp__.match(self.repo_path): + raise AirflowException( + f"repo_path should have form of /Repos/{{folder}}/{{repo-name}}, got '{self.repo_path}'" + ) + payload["path"] = self.repo_path + existing_repo_id = None + if self.repo_path is not None: + existing_repo_id = self._hook.get_repo_by_path(self.repo_path) + if existing_repo_id is not None and not self.ignore_existing_repo: + raise AirflowException(f"Repo with path '{self.repo_path}' already exists") + if existing_repo_id is None: + result = self._hook.create_repo(payload) + repo_id = result["id"] + else: + repo_id = existing_repo_id + # update repo if necessary + if self.branch is not None: + self._hook.update_repo(str(repo_id), {"branch": str(self.branch)}) + elif self.tag is not None: + self._hook.update_repo(str(repo_id), {"tag": str(self.tag)}) + + return repo_id
+ + +
[docs]class DatabricksReposUpdateOperator(BaseOperator): + """ + Updates specified repository to a given branch or tag using the PATCH api/2.0/repos API endpoint. + + See: https://docs.databricks.com/dev-tools/api/latest/repos.html#operation/update-repo + + :param branch: optional name of branch to update to. Should be specified if ``tag`` is omitted + :param tag: optional name of tag to update to. Should be specified if ``branch`` is omitted + :param repo_id: optional ID of existing repository. Should be specified if ``repo_path`` is omitted + :param repo_path: optional path of existing repository. Should be specified if ``repo_id`` is omitted + :param databricks_conn_id: Reference to the :ref:`Databricks connection <howto/connection:databricks>`. + By default and in the common case this will be ``databricks_default``. To use + token based authentication, provide the key ``token`` in the extra field for the + connection and create the key ``host`` and leave the ``host`` field empty. (templated) + :param databricks_retry_limit: Amount of times retry if the Databricks backend is + unreachable. Its value must be greater than or equal to 1. + :param databricks_retry_delay: Number of seconds to wait between retries (it + might be a floating point number). + """ + + # Used in airflow.models.BaseOperator +
[docs] template_fields: Sequence[str] = ("repo_path", "tag", "branch", "databricks_conn_id")
+ + def __init__( + self, + *, + branch: str | None = None, + tag: str | None = None, + repo_id: str | None = None, + repo_path: str | None = None, + databricks_conn_id: str = "databricks_default", + databricks_retry_limit: int = 3, + databricks_retry_delay: int = 1, + **kwargs, + ) -> None: + """Create a new ``DatabricksReposUpdateOperator``.""" + super().__init__(**kwargs) + self.databricks_conn_id = databricks_conn_id + self.databricks_retry_limit = databricks_retry_limit + self.databricks_retry_delay = databricks_retry_delay + if branch is not None and tag is not None: + raise AirflowException("Only one of branch or tag should be provided, but not both") + if branch is None and tag is None: + raise AirflowException("One of branch or tag should be provided") + if repo_id is not None and repo_path is not None: + raise AirflowException("Only one of repo_id or repo_path should be provided, but not both") + if repo_id is None and repo_path is None: + raise AirflowException("One of repo_id or repo_path should be provided") + self.repo_path = repo_path + self.repo_id = repo_id + self.branch = branch + self.tag = tag + + @cached_property + def _hook(self) -> DatabricksHook: + return DatabricksHook( + self.databricks_conn_id, + retry_limit=self.databricks_retry_limit, + retry_delay=self.databricks_retry_delay, + caller="DatabricksReposUpdateOperator", + ) + +
[docs] def execute(self, context: Context): + if self.repo_path is not None: + self.repo_id = self._hook.get_repo_by_path(self.repo_path) + if self.repo_id is None: + raise AirflowException(f"Can't find Repo ID for path '{self.repo_path}'") + if self.branch is not None: + payload = {"branch": str(self.branch)} + else: + payload = {"tag": str(self.tag)} + + result = self._hook.update_repo(str(self.repo_id), payload) + return result["head_commit_id"]
+ + +
[docs]class DatabricksReposDeleteOperator(BaseOperator): + """ + Deletes specified repository using the DELETE api/2.0/repos API endpoint. + + See: https://docs.databricks.com/dev-tools/api/latest/repos.html#operation/delete-repo + + :param repo_id: optional ID of existing repository. Should be specified if ``repo_path`` is omitted + :param repo_path: optional path of existing repository. Should be specified if ``repo_id`` is omitted + :param databricks_conn_id: Reference to the :ref:`Databricks connection <howto/connection:databricks>`. + By default and in the common case this will be ``databricks_default``. To use + token based authentication, provide the key ``token`` in the extra field for the + connection and create the key ``host`` and leave the ``host`` field empty. (templated) + :param databricks_retry_limit: Amount of times retry if the Databricks backend is + unreachable. Its value must be greater than or equal to 1. + :param databricks_retry_delay: Number of seconds to wait between retries (it + might be a floating point number). + """ + + # Used in airflow.models.BaseOperator +
[docs] template_fields: Sequence[str] = ("repo_path", "databricks_conn_id")
+ + def __init__( + self, + *, + repo_id: str | None = None, + repo_path: str | None = None, + databricks_conn_id: str = "databricks_default", + databricks_retry_limit: int = 3, + databricks_retry_delay: int = 1, + **kwargs, + ) -> None: + """Create a new ``DatabricksReposDeleteOperator``.""" + super().__init__(**kwargs) + self.databricks_conn_id = databricks_conn_id + self.databricks_retry_limit = databricks_retry_limit + self.databricks_retry_delay = databricks_retry_delay + if repo_id is not None and repo_path is not None: + raise AirflowException("Only one of repo_id or repo_path should be provided, but not both") + if repo_id is None and repo_path is None: + raise AirflowException("One of repo_id repo_path tag should be provided") + self.repo_path = repo_path + self.repo_id = repo_id + + @cached_property + def _hook(self) -> DatabricksHook: + return DatabricksHook( + self.databricks_conn_id, + retry_limit=self.databricks_retry_limit, + retry_delay=self.databricks_retry_delay, + caller="DatabricksReposDeleteOperator", + ) + +
[docs] def execute(self, context: Context): + if self.repo_path is not None: + self.repo_id = self._hook.get_repo_by_path(self.repo_path) + if self.repo_id is None: + raise AirflowException(f"Can't find Repo ID for path '{self.repo_path}'") + + self._hook.delete_repo(str(self.repo_id))
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/operators/databricks_sql.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/operators/databricks_sql.html new file mode 100644 index 00000000000..76164ad3b81 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/operators/databricks_sql.html @@ -0,0 +1,1194 @@ + + + + + + + + + + + + airflow.providers.databricks.operators.databricks_sql — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.databricks.operators.databricks_sql

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""This module contains Databricks operators."""
+
+from __future__ import annotations
+
+import csv
+import json
+from typing import TYPE_CHECKING, Any, Sequence
+
+from databricks.sql.utils import ParamEscaper
+
+from airflow.exceptions import AirflowException
+from airflow.models import BaseOperator
+from airflow.providers.common.sql.operators.sql import SQLExecuteQueryOperator
+from airflow.providers.databricks.hooks.databricks_sql import DatabricksSqlHook
+
+if TYPE_CHECKING:
+    from airflow.utils.context import Context
+
+
+
[docs]class DatabricksSqlOperator(SQLExecuteQueryOperator): + """ + Executes SQL code in a Databricks SQL endpoint or a Databricks cluster. + + .. seealso:: + For more information on how to use this operator, take a look at the guide: + :ref:`howto/operator:DatabricksSqlOperator` + + :param databricks_conn_id: Reference to + :ref:`Databricks connection id<howto/connection:databricks>` (templated) + :param http_path: Optional string specifying HTTP path of Databricks SQL Endpoint or cluster. + If not specified, it should be either specified in the Databricks connection's extra parameters, + or ``sql_endpoint_name`` must be specified. + :param sql_endpoint_name: Optional name of Databricks SQL Endpoint. If not specified, ``http_path`` must + be provided as described above. + :param sql: the SQL code to be executed as a single string, or + a list of str (sql statements), or a reference to a template file. (templated) + Template references are recognized by str ending in '.sql' + :param parameters: (optional) the parameters to render the SQL query with. + :param session_configuration: An optional dictionary of Spark session parameters. Defaults to None. + If not specified, it could be specified in the Databricks connection's extra parameters. + :param client_parameters: Additional parameters internal to Databricks SQL Connector parameters + :param http_headers: An optional list of (k, v) pairs that will be set as HTTP headers on every request. + (templated) + :param catalog: An optional initial catalog to use. Requires DBR version 9.0+ (templated) + :param schema: An optional initial schema to use. Requires DBR version 9.0+ (templated) + :param output_path: optional string specifying the file to which write selected data. (templated) + :param output_format: format of output data if ``output_path` is specified. + Possible values are ``csv``, ``json``, ``jsonl``. Default is ``csv``. + :param csv_params: parameters that will be passed to the ``csv.DictWriter`` class used to write CSV data. + """ + +
[docs] template_fields: Sequence[str] = tuple( + {"_output_path", "schema", "catalog", "http_headers", "databricks_conn_id"} + | set(SQLExecuteQueryOperator.template_fields) + )
+ +
[docs] template_ext: Sequence[str] = (".sql",)
+
[docs] template_fields_renderers = {"sql": "sql"}
+
[docs] conn_id_field = "databricks_conn_id"
+ + def __init__( + self, + *, + databricks_conn_id: str = DatabricksSqlHook.default_conn_name, + http_path: str | None = None, + sql_endpoint_name: str | None = None, + session_configuration=None, + http_headers: list[tuple[str, str]] | None = None, + catalog: str | None = None, + schema: str | None = None, + output_path: str | None = None, + output_format: str = "csv", + csv_params: dict[str, Any] | None = None, + client_parameters: dict[str, Any] | None = None, + **kwargs, + ) -> None: + super().__init__(conn_id=databricks_conn_id, **kwargs) + self.databricks_conn_id = databricks_conn_id + self._output_path = output_path + self._output_format = output_format + self._csv_params = csv_params + self.http_path = http_path + self.sql_endpoint_name = sql_endpoint_name + self.session_configuration = session_configuration + self.client_parameters = {} if client_parameters is None else client_parameters + self.hook_params = kwargs.pop("hook_params", {}) + self.http_headers = http_headers + self.catalog = catalog + self.schema = schema + +
[docs] def get_db_hook(self) -> DatabricksSqlHook: + hook_params = { + "http_path": self.http_path, + "session_configuration": self.session_configuration, + "sql_endpoint_name": self.sql_endpoint_name, + "http_headers": self.http_headers, + "catalog": self.catalog, + "schema": self.schema, + "caller": "DatabricksSqlOperator", + "return_tuple": True, + **self.client_parameters, + **self.hook_params, + } + return DatabricksSqlHook(self.databricks_conn_id, **hook_params)
+ + def _should_run_output_processing(self) -> bool: + return self.do_xcom_push or bool(self._output_path) + + def _process_output(self, results: list[Any], descriptions: list[Sequence[Sequence] | None]) -> list[Any]: + if not self._output_path: + return list(zip(descriptions, results)) + if not self._output_format: + raise AirflowException("Output format should be specified!") + # Output to a file only the result of last query + last_description = descriptions[-1] + last_results = results[-1] + if last_description is None: + raise AirflowException("There is missing description present for the output file. .") + field_names = [field[0] for field in last_description] + if self._output_format.lower() == "csv": + with open(self._output_path, "w", newline="") as file: + if self._csv_params: + csv_params = self._csv_params + else: + csv_params = {} + write_header = csv_params.get("header", True) + if "header" in csv_params: + del csv_params["header"] + writer = csv.DictWriter(file, fieldnames=field_names, **csv_params) + if write_header: + writer.writeheader() + for row in last_results: + writer.writerow(row._asdict()) + elif self._output_format.lower() == "json": + with open(self._output_path, "w") as file: + file.write(json.dumps([row._asdict() for row in last_results])) + elif self._output_format.lower() == "jsonl": + with open(self._output_path, "w") as file: + for row in last_results: + file.write(json.dumps(row._asdict())) + file.write("\n") + else: + raise AirflowException(f"Unsupported output format: '{self._output_format}'") + return list(zip(descriptions, results))
+ + +
[docs]COPY_INTO_APPROVED_FORMATS = ["CSV", "JSON", "AVRO", "ORC", "PARQUET", "TEXT", "BINARYFILE"]
+ + +
[docs]class DatabricksCopyIntoOperator(BaseOperator): + """ + Executes COPY INTO command in a Databricks SQL endpoint or a Databricks cluster. + + COPY INTO command is constructed from individual pieces, that are described in + `documentation <https://docs.databricks.com/sql/language-manual/delta-copy-into.html>`_. + + .. seealso:: + For more information on how to use this operator, take a look at the guide: + :ref:`howto/operator:DatabricksSqlCopyIntoOperator` + + :param table_name: Required name of the table. (templated) + :param file_location: Required location of files to import. (templated) + :param file_format: Required file format. Supported formats are + ``CSV``, ``JSON``, ``AVRO``, ``ORC``, ``PARQUET``, ``TEXT``, ``BINARYFILE``. + :param databricks_conn_id: Reference to + :ref:`Databricks connection id<howto/connection:databricks>` (templated) + :param http_path: Optional string specifying HTTP path of Databricks SQL Endpoint or cluster. + If not specified, it should be either specified in the Databricks connection's extra parameters, + or ``sql_endpoint_name`` must be specified. + :param sql_endpoint_name: Optional name of Databricks SQL Endpoint. + If not specified, ``http_path`` must be provided as described above. + :param session_configuration: An optional dictionary of Spark session parameters. Defaults to None. + If not specified, it could be specified in the Databricks connection's extra parameters. + :param http_headers: An optional list of (k, v) pairs that will be set as HTTP headers on every request + :param catalog: An optional initial catalog to use. Requires DBR version 9.0+ + :param schema: An optional initial schema to use. Requires DBR version 9.0+ + :param client_parameters: Additional parameters internal to Databricks SQL Connector parameters + :param files: optional list of files to import. Can't be specified together with ``pattern``. (templated) + :param pattern: optional regex string to match file names to import. + Can't be specified together with ``files``. + :param expression_list: optional string that will be used in the ``SELECT`` expression. + :param credential: optional credential configuration for authentication against a source location. + :param storage_credential: optional Unity Catalog storage credential for destination. + :param encryption: optional encryption configuration for a specified location. + :param format_options: optional dictionary with options specific for a given file format. + :param force_copy: optional bool to control forcing of data import + (could be also specified in ``copy_options``). + :param validate: optional configuration for schema & data validation. ``True`` forces validation + of all rows, integer number - validate only N first rows + :param copy_options: optional dictionary of copy options. Right now only ``force`` option is supported. + """ + +
[docs] template_fields: Sequence[str] = ( + "file_location", + "files", + "table_name", + "databricks_conn_id", + )
+ + def __init__( + self, + *, + table_name: str, + file_location: str, + file_format: str, + databricks_conn_id: str = DatabricksSqlHook.default_conn_name, + http_path: str | None = None, + sql_endpoint_name: str | None = None, + session_configuration=None, + http_headers: list[tuple[str, str]] | None = None, + client_parameters: dict[str, Any] | None = None, + catalog: str | None = None, + schema: str | None = None, + files: list[str] | None = None, + pattern: str | None = None, + expression_list: str | None = None, + credential: dict[str, str] | None = None, + storage_credential: str | None = None, + encryption: dict[str, str] | None = None, + format_options: dict[str, str] | None = None, + force_copy: bool | None = None, + copy_options: dict[str, str] | None = None, + validate: bool | int | None = None, + **kwargs, + ) -> None: + """Create a new ``DatabricksSqlOperator``.""" + super().__init__(**kwargs) + if files is not None and pattern is not None: + raise AirflowException("Only one of 'pattern' or 'files' should be specified") + if table_name == "": + raise AirflowException("table_name shouldn't be empty") + if file_location == "": + raise AirflowException("file_location shouldn't be empty") + if file_format not in COPY_INTO_APPROVED_FORMATS: + raise AirflowException(f"file_format '{file_format}' isn't supported") + self.files = files + self._pattern = pattern + self._file_format = file_format + self.databricks_conn_id = databricks_conn_id + self._http_path = http_path + self._sql_endpoint_name = sql_endpoint_name + self.session_config = session_configuration + self.table_name = table_name + self._catalog = catalog + self._schema = schema + self.file_location = file_location + self._expression_list = expression_list + self._credential = credential + self._storage_credential = storage_credential + self._encryption = encryption + self._format_options = format_options + self._copy_options = copy_options or {} + self._validate = validate + self._http_headers = http_headers + self._client_parameters = client_parameters or {} + if force_copy is not None: + self._copy_options["force"] = "true" if force_copy else "false" + + def _get_hook(self) -> DatabricksSqlHook: + return DatabricksSqlHook( + self.databricks_conn_id, + http_path=self._http_path, + session_configuration=self.session_config, + sql_endpoint_name=self._sql_endpoint_name, + http_headers=self._http_headers, + catalog=self._catalog, + schema=self._schema, + caller="DatabricksCopyIntoOperator", + **self._client_parameters, + ) + + @staticmethod + def _generate_options( + name: str, + escaper: ParamEscaper, + opts: dict[str, str] | None = None, + escape_key: bool = True, + ) -> str: + formatted_opts = "" + if opts: + pairs = [ + f"{escaper.escape_item(k) if escape_key else k} = {escaper.escape_item(v)}" + for k, v in opts.items() + ] + formatted_opts = f"{name} ({', '.join(pairs)})" + + return formatted_opts + + def _create_sql_query(self) -> str: + escaper = ParamEscaper() + maybe_with = "" + if self._encryption is not None or self._credential is not None: + maybe_encryption = "" + if self._encryption is not None: + maybe_encryption = self._generate_options("ENCRYPTION", escaper, self._encryption, False) + maybe_credential = "" + if self._credential is not None: + maybe_credential = self._generate_options("CREDENTIAL", escaper, self._credential, False) + maybe_with = f" WITH ({maybe_credential} {maybe_encryption})" + location = escaper.escape_item(self.file_location) + maybe_with + if self._expression_list is not None: + location = f"(SELECT {self._expression_list} FROM {location})" + files_or_pattern = "" + if self._pattern is not None: + files_or_pattern = f"PATTERN = {escaper.escape_item(self._pattern)}\n" + elif self.files is not None: + files_or_pattern = f"FILES = {escaper.escape_item(self.files)}\n" + format_options = self._generate_options("FORMAT_OPTIONS", escaper, self._format_options) + "\n" + copy_options = self._generate_options("COPY_OPTIONS", escaper, self._copy_options) + "\n" + storage_cred = "" + if self._storage_credential: + storage_cred = f" WITH (CREDENTIAL {self._storage_credential})" + validation = "" + if self._validate is not None: + if isinstance(self._validate, bool): + if self._validate: + validation = "VALIDATE ALL\n" + elif isinstance(self._validate, int): + if self._validate < 0: + raise AirflowException( + f"Number of rows for validation should be positive, got: {self._validate}" + ) + validation = f"VALIDATE {self._validate} ROWS\n" + else: + raise AirflowException(f"Incorrect data type for validate parameter: {type(self._validate)}") + # TODO: think on how to make sure that table_name and expression_list aren't used for SQL injection + sql = f"""COPY INTO {self.table_name}{storage_cred} +FROM {location} +FILEFORMAT = {self._file_format} +{validation}{files_or_pattern}{format_options}{copy_options} +""" + return sql.strip() + +
[docs] def execute(self, context: Context) -> Any: + sql = self._create_sql_query() + self.log.info("Executing: %s", sql) + hook = self._get_hook() + hook.run(sql)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/sensors/databricks_partition.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/sensors/databricks_partition.html new file mode 100644 index 00000000000..42f0b99832d --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/sensors/databricks_partition.html @@ -0,0 +1,1077 @@ + + + + + + + + + + + + airflow.providers.databricks.sensors.databricks_partition — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.databricks.sensors.databricks_partition

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+"""This module contains Databricks sensors."""
+
+from __future__ import annotations
+
+from datetime import datetime
+from functools import cached_property
+from typing import TYPE_CHECKING, Any, Callable, Sequence
+
+from databricks.sql.utils import ParamEscaper
+
+from airflow.exceptions import AirflowException, AirflowSkipException
+from airflow.providers.common.sql.hooks.sql import fetch_all_handler
+from airflow.providers.databricks.hooks.databricks_sql import DatabricksSqlHook
+from airflow.sensors.base import BaseSensorOperator
+
+if TYPE_CHECKING:
+    from airflow.utils.context import Context
+
+
+
[docs]class DatabricksPartitionSensor(BaseSensorOperator): + """ + Sensor to detect the presence of table partitions in Databricks. + + :param databricks_conn_id: Reference to :ref:`Databricks + connection id<howto/connection:databricks>` (templated), defaults to + DatabricksSqlHook.default_conn_name. + :param sql_warehouse_name: Optional name of Databricks SQL warehouse. If not specified, ``http_path`` + must be provided as described below, defaults to None + :param http_path: Optional string specifying HTTP path of Databricks SQL warehouse or All Purpose cluster. + If not specified, it should be either specified in the Databricks connection's + extra parameters, or ``sql_warehouse_name`` must be specified. + :param session_configuration: An optional dictionary of Spark session parameters. If not specified, + it could be specified in the Databricks connection's extra parameters, defaults to None + :param http_headers: An optional list of (k, v) pairs + that will be set as HTTP headers on every request. (templated). + :param catalog: An optional initial catalog to use. + Requires Databricks Runtime version 9.0+ (templated), defaults to "" + :param schema: An optional initial schema to use. + Requires Databricks Runtime version 9.0+ (templated), defaults to "default" + :param table_name: Name of the table to check partitions. + :param partitions: Name of the partitions to check. + Example: {"date": "2023-01-03", "name": ["abc", "def"]} + :param partition_operator: Optional comparison operator for partitions, such as >=. + :param handler: Handler for DbApiHook.run() to return results, defaults to fetch_all_handler + :param client_parameters: Additional parameters internal to Databricks SQL connector parameters. + """ + +
[docs] template_fields: Sequence[str] = ( + "databricks_conn_id", + "catalog", + "schema", + "table_name", + "partitions", + "http_headers", + )
+ +
[docs] template_ext: Sequence[str] = (".sql",)
+
[docs] template_fields_renderers = {"sql": "sql"}
+ + def __init__( + self, + *, + databricks_conn_id: str = DatabricksSqlHook.default_conn_name, + http_path: str | None = None, + sql_warehouse_name: str | None = None, + session_configuration=None, + http_headers: list[tuple[str, str]] | None = None, + catalog: str = "", + schema: str = "default", + table_name: str, + partitions: dict, + partition_operator: str = "=", + handler: Callable[[Any], Any] = fetch_all_handler, + client_parameters: dict[str, Any] | None = None, + **kwargs, + ) -> None: + self.databricks_conn_id = databricks_conn_id + self._http_path = http_path + self._sql_warehouse_name = sql_warehouse_name + self.session_config = session_configuration + self.http_headers = http_headers + self.catalog = catalog + self.schema = schema + self.caller = "DatabricksPartitionSensor" + self.partitions = partitions + self.partition_operator = partition_operator + self.table_name = table_name + self.client_parameters = client_parameters or {} + self.hook_params = kwargs.pop("hook_params", {}) + self.handler = handler + self.escaper = ParamEscaper() + super().__init__(**kwargs) + + def _sql_sensor(self, sql): + """Execute the supplied SQL statement using the hook object.""" + hook = self._get_hook + sql_result = hook.run( + sql, + handler=self.handler if self.do_xcom_push else None, + ) + self.log.debug("SQL result: %s", sql_result) + return sql_result + + @cached_property + def _get_hook(self) -> DatabricksSqlHook: + """Create and return a DatabricksSqlHook object.""" + return DatabricksSqlHook( + self.databricks_conn_id, + self._http_path, + self._sql_warehouse_name, + self.session_config, + self.http_headers, + self.catalog, + self.schema, + self.caller, + **self.client_parameters, + **self.hook_params, + ) + + def _check_table_partitions(self) -> list: + """Generate the fully qualified table name, generate partition, and call the _sql_sensor method.""" + if self.table_name.split(".")[0] == "delta": + _fully_qualified_table_name = self.table_name + else: + _fully_qualified_table_name = f"{self.catalog}.{self.schema}.{self.table_name}" + self.log.debug("Table name generated from arguments: %s", _fully_qualified_table_name) + _joiner_val = " AND " + _prefix = f"SELECT 1 FROM {_fully_qualified_table_name} WHERE" + _suffix = " LIMIT 1" + + partition_sql = self._generate_partition_query( + prefix=_prefix, + suffix=_suffix, + joiner_val=_joiner_val, + opts=self.partitions, + table_name=_fully_qualified_table_name, + escape_key=False, + ) + return self._sql_sensor(partition_sql) + + def _generate_partition_query( + self, + prefix: str, + suffix: str, + joiner_val: str, + table_name: str, + opts: dict[str, str] | None = None, + escape_key: bool = False, + ) -> str: + """ + Query the table for available partitions. + + Generates the SQL query based on the partition data types. + * For a list, it prepares the SQL in the format: + column_name in (value1, value2,...) + * For a numeric type, it prepares the format: + column_name =(or other provided operator such as >=) value + * For a date type, it prepares the format: + column_name =(or other provided operator such as >=) value + Once the filter predicates have been generated like above, the query + is prepared to be executed using the prefix and suffix supplied, which are: + "SELECT 1 FROM {_fully_qualified_table_name} WHERE" and "LIMIT 1". + """ + partition_columns = self._sql_sensor(f"DESCRIBE DETAIL {table_name}")[0][7] + self.log.debug("Partition columns: %s", partition_columns) + if len(partition_columns) < 1: + # TODO: remove this if block when min_airflow_version is set to higher than 2.7.1 + message = f"Table {table_name} does not have partitions" + if self.soft_fail: + raise AirflowSkipException(message) + raise AirflowException(message) + + formatted_opts = "" + if opts: + output_list = [] + for partition_col, partition_value in opts.items(): + if escape_key: + partition_col = self.escaper.escape_item(partition_col) + if partition_col in partition_columns: + if isinstance(partition_value, list): + output_list.append(f"""{partition_col} in {tuple(partition_value)}""") + self.log.debug("List formatting for partitions: %s", output_list) + if isinstance(partition_value, (int, float, complex)): + output_list.append( + f"""{partition_col}{self.partition_operator}{self.escaper.escape_item(partition_value)}""" + ) + if isinstance(partition_value, (str, datetime)): + output_list.append( + f"""{partition_col}{self.partition_operator}{self.escaper.escape_item(partition_value)}""" + ) + else: + # TODO: remove this if block when min_airflow_version is set to higher than 2.7.1 + message = f"Column {partition_col} not part of table partitions: {partition_columns}" + if self.soft_fail: + raise AirflowSkipException(message) + raise AirflowException(message) + else: + # Raises exception if the table does not have any partitions. + # TODO: remove this if block when min_airflow_version is set to higher than 2.7.1 + message = "No partitions specified to check with the sensor." + if self.soft_fail: + raise AirflowSkipException(message) + raise AirflowException(message) + formatted_opts = f"{prefix} {joiner_val.join(output_list)} {suffix}" + self.log.debug("Formatted options: %s", formatted_opts) + + return formatted_opts.strip() + +
[docs] def poke(self, context: Context) -> bool: + """Check the table partitions and return the results.""" + partition_result = self._check_table_partitions() + self.log.debug("Partition sensor result: %s", partition_result) + if partition_result: + return True + else: + # TODO: remove this if block when min_airflow_version is set to higher than 2.7.1 + message = f"Specified partition(s): {self.partitions} were not found." + if self.soft_fail: + raise AirflowSkipException(message) + raise AirflowException(message)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/sensors/databricks_sql.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/sensors/databricks_sql.html new file mode 100644 index 00000000000..f54ff273c1d --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/sensors/databricks_sql.html @@ -0,0 +1,977 @@ + + + + + + + + + + + + airflow.providers.databricks.sensors.databricks_sql — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.databricks.sensors.databricks_sql

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+"""This module contains Databricks sensors."""
+
+from __future__ import annotations
+
+from functools import cached_property
+from typing import TYPE_CHECKING, Any, Callable, Iterable, Sequence
+
+from airflow.exceptions import AirflowException, AirflowSkipException
+from airflow.providers.common.sql.hooks.sql import fetch_all_handler
+from airflow.providers.databricks.hooks.databricks_sql import DatabricksSqlHook
+from airflow.sensors.base import BaseSensorOperator
+
+if TYPE_CHECKING:
+    from airflow.utils.context import Context
+
+
+
[docs]class DatabricksSqlSensor(BaseSensorOperator): + """ + Sensor that runs a SQL query on Databricks. + + :param databricks_conn_id: Reference to :ref:`Databricks + connection id<howto/connection:databricks>` (templated), defaults to + DatabricksSqlHook.default_conn_name. + :param sql_warehouse_name: Optional name of Databricks SQL warehouse. If not specified, ``http_path`` + must be provided as described below, defaults to None + :param http_path: Optional string specifying HTTP path of Databricks SQL warehouse or All Purpose cluster. + If not specified, it should be either specified in the Databricks connection's + extra parameters, or ``sql_warehouse_name`` must be specified. + :param session_configuration: An optional dictionary of Spark session parameters. If not specified, + it could be specified in the Databricks connection's extra parameters, defaults to None + :param http_headers: An optional list of (k, v) pairs + that will be set as HTTP headers on every request. (templated). + :param catalog: An optional initial catalog to use. + Requires Databricks Runtime version 9.0+ (templated), defaults to "" + :param schema: An optional initial schema to use. + Requires Databricks Runtime version 9.0+ (templated), defaults to "default" + :param sql: SQL statement to be executed. + :param handler: Handler for DbApiHook.run() to return results, defaults to fetch_all_handler + :param client_parameters: Additional parameters internal to Databricks SQL connector parameters. + """ + +
[docs] template_fields: Sequence[str] = ( + "databricks_conn_id", + "sql", + "catalog", + "schema", + "http_headers", + )
+ +
[docs] template_ext: Sequence[str] = (".sql",)
+
[docs] template_fields_renderers = {"sql": "sql"}
+ + def __init__( + self, + *, + databricks_conn_id: str = DatabricksSqlHook.default_conn_name, + http_path: str | None = None, + sql_warehouse_name: str | None = None, + session_configuration=None, + http_headers: list[tuple[str, str]] | None = None, + catalog: str = "", + schema: str = "default", + sql: str | Iterable[str], + handler: Callable[[Any], Any] = fetch_all_handler, + client_parameters: dict[str, Any] | None = None, + **kwargs, + ) -> None: + """Create DatabricksSqlSensor object using the specified input arguments.""" + self.databricks_conn_id = databricks_conn_id + self._http_path = http_path + self._sql_warehouse_name = sql_warehouse_name + self.session_config = session_configuration + self.http_headers = http_headers + self.catalog = catalog + self.schema = schema + self.sql = sql + self.caller = "DatabricksSqlSensor" + self.client_parameters = client_parameters or {} + self.hook_params = kwargs.pop("hook_params", {}) + self.handler = handler + super().__init__(**kwargs) + + @cached_property +
[docs] def hook(self) -> DatabricksSqlHook: + """Creates and returns a DatabricksSqlHook object.""" + return DatabricksSqlHook( + self.databricks_conn_id, + self._http_path, + self._sql_warehouse_name, + self.session_config, + self.http_headers, + self.catalog, + self.schema, + self.caller, + **self.client_parameters, + **self.hook_params, + )
+ + def _get_results(self) -> bool: + """Use the Databricks SQL hook and run the specified SQL query.""" + if not (self._http_path or self._sql_warehouse_name): + # TODO: remove this if block when min_airflow_version is set to higher than 2.7.1 + message = ( + "Databricks SQL warehouse/cluster configuration missing. Please specify either" + " http_path or sql_warehouse_name." + ) + if self.soft_fail: + raise AirflowSkipException(message) + raise AirflowException(message) + hook = self.hook + sql_result = hook.run( + self.sql, + handler=self.handler if self.do_xcom_push else None, + ) + self.log.debug("SQL result: %s", sql_result) + return bool(sql_result) + +
[docs] def poke(self, context: Context) -> bool: + """Sensor poke function to get and return results from the SQL sensor.""" + return self._get_results()
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/triggers/databricks.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/triggers/databricks.html new file mode 100644 index 00000000000..e655ad635b6 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/triggers/databricks.html @@ -0,0 +1,943 @@ + + + + + + + + + + + + airflow.providers.databricks.triggers.databricks — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.databricks.triggers.databricks

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import asyncio
+from typing import Any
+
+from airflow.providers.databricks.hooks.databricks import DatabricksHook
+from airflow.triggers.base import BaseTrigger, TriggerEvent
+
+
+
[docs]class DatabricksExecutionTrigger(BaseTrigger): + """ + The trigger handles the logic of async communication with DataBricks API. + + :param run_id: id of the run + :param databricks_conn_id: Reference to the :ref:`Databricks connection <howto/connection:databricks>`. + :param polling_period_seconds: Controls the rate of the poll for the result of this run. + By default, the trigger will poll every 30 seconds. + :param retry_limit: The number of times to retry the connection in case of service outages. + :param retry_delay: The number of seconds to wait between retries. + :param retry_args: An optional dictionary with arguments passed to ``tenacity.Retrying`` class. + :param run_page_url: The run page url. + """ + + def __init__( + self, + run_id: int, + databricks_conn_id: str, + polling_period_seconds: int = 30, + retry_limit: int = 3, + retry_delay: int = 10, + retry_args: dict[Any, Any] | None = None, + run_page_url: str | None = None, + repair_run: bool = False, + ) -> None: + super().__init__() + self.run_id = run_id + self.databricks_conn_id = databricks_conn_id + self.polling_period_seconds = polling_period_seconds + self.retry_limit = retry_limit + self.retry_delay = retry_delay + self.retry_args = retry_args + self.run_page_url = run_page_url + self.repair_run = repair_run + self.hook = DatabricksHook( + databricks_conn_id, + retry_limit=self.retry_limit, + retry_delay=self.retry_delay, + retry_args=retry_args, + ) + +
[docs] def serialize(self) -> tuple[str, dict[str, Any]]: + return ( + "airflow.providers.databricks.triggers.databricks.DatabricksExecutionTrigger", + { + "run_id": self.run_id, + "databricks_conn_id": self.databricks_conn_id, + "polling_period_seconds": self.polling_period_seconds, + "retry_limit": self.retry_limit, + "retry_delay": self.retry_delay, + "retry_args": self.retry_args, + "run_page_url": self.run_page_url, + "repair_run": self.repair_run, + }, + )
+ +
[docs] async def run(self): + async with self.hook: + while True: + run_state = await self.hook.a_get_run_state(self.run_id) + if run_state.is_terminal: + yield TriggerEvent( + { + "run_id": self.run_id, + "run_page_url": self.run_page_url, + "run_state": run_state.to_json(), + "repair_run": self.repair_run, + } + ) + return + + self.log.info( + "run-id %s in run state %s. sleeping for %s seconds", + self.run_id, + run_state, + self.polling_period_seconds, + ) + await asyncio.sleep(self.polling_period_seconds)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/utils/databricks.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/utils/databricks.html new file mode 100644 index 00000000000..01a0b85c79c --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/airflow/providers/databricks/utils/databricks.html @@ -0,0 +1,905 @@ + + + + + + + + + + + + airflow.providers.databricks.utils.databricks — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.databricks.utils.databricks

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from airflow.exceptions import AirflowException
+from airflow.providers.databricks.hooks.databricks import RunState
+
+
+
[docs]def normalise_json_content(content, json_path: str = "json") -> str | bool | list | dict: + """ + Normalize content or all values of content if it is a dict to a string. + + The function will throw if content contains non-string or non-numeric non-boolean + types. The reason why we have this function is because the ``self.json`` field + must be a dict with only string values. This is because ``render_template`` will + fail for numerical values. + + The only one exception is when we have boolean values, they can not be converted + to string type because databricks does not understand 'True' or 'False' values. + """ + normalise = normalise_json_content + if isinstance(content, (str, bool)): + return content + elif isinstance(content, (int, float)): + # Databricks can tolerate either numeric or string types in the API backend. + return str(content) + elif isinstance(content, (list, tuple)): + return [normalise(e, f"{json_path}[{i}]") for i, e in enumerate(content)] + elif isinstance(content, dict): + return {k: normalise(v, f"{json_path}[{k}]") for k, v in content.items()} + else: + param_type = type(content) + msg = f"Type {param_type} used for parameter {json_path} is not a number or a string" + raise AirflowException(msg)
+ + +
[docs]def validate_trigger_event(event: dict): + """ + Validate correctness of the event received from DatabricksExecutionTrigger. + + See: :class:`~airflow.providers.databricks.triggers.databricks.DatabricksExecutionTrigger`. + """ + keys_to_check = ["run_id", "run_page_url", "run_state"] + for key in keys_to_check: + if key not in event: + raise AirflowException(f"Could not find `{key}` in the event: {event}") + + try: + RunState.from_json(event["run_state"]) + except Exception: + raise AirflowException(f'Run state returned by the Trigger is incorrect: {event["run_state"]}')
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/index.html new file mode 100644 index 00000000000..f1eb11a8f79 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/index.html @@ -0,0 +1,850 @@ + + + + + + + + + + + + Overview: module code — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/tests/system/providers/databricks/example_databricks.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/tests/system/providers/databricks/example_databricks.html new file mode 100644 index 00000000000..13e86a2184c --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/tests/system/providers/databricks/example_databricks.html @@ -0,0 +1,996 @@ + + + + + + + + + + + + tests.system.providers.databricks.example_databricks — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for tests.system.providers.databricks.example_databricks

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""
+This is an example DAG which uses the DatabricksSubmitRunOperator.
+In this example, we create two tasks which execute sequentially.
+The first task is to run a notebook at the workspace path "/test"
+and the second task is to run a JAR uploaded to DBFS. Both,
+tasks use new clusters.
+
+Because we have set a downstream dependency on the notebook task,
+the spark jar task will NOT run until the notebook task completes
+successfully.
+
+The definition of a successful run is if the run has a result_state of "SUCCESS".
+For more information about the state of a run refer to
+https://docs.databricks.com/api/latest/jobs.html#runstate
+"""
+
+from __future__ import annotations
+
+import os
+from datetime import datetime
+
+from airflow import DAG
+from airflow.providers.databricks.operators.databricks import (
+    DatabricksCreateJobsOperator,
+    DatabricksRunNowOperator,
+    DatabricksSubmitRunOperator,
+)
+
+
[docs]ENV_ID = os.environ.get("SYSTEM_TESTS_ENV_ID")
+
[docs]DAG_ID = "example_databricks_operator"
+ +with DAG( + dag_id=DAG_ID, + schedule="@daily", + start_date=datetime(2021, 1, 1), + tags=["example"], + catchup=False, +) as dag: + # [START howto_operator_databricks_jobs_create_json] + # Example of using the JSON parameter to initialize the operator. +
[docs] job = { + "tasks": [ + { + "task_key": "test", + "job_cluster_key": "job_cluster", + "notebook_task": { + "notebook_path": "/Shared/test", + }, + }, + ], + "job_clusters": [ + { + "job_cluster_key": "job_cluster", + "new_cluster": { + "spark_version": "7.3.x-scala2.12", + "node_type_id": "i3.xlarge", + "num_workers": 2, + }, + }, + ], + }
+ + jobs_create_json = DatabricksCreateJobsOperator(task_id="jobs_create_json", json=job) + # [END howto_operator_databricks_jobs_create_json] + + # [START howto_operator_databricks_jobs_create_named] + # Example of using the named parameters to initialize the operator. + tasks = [ + { + "task_key": "test", + "job_cluster_key": "job_cluster", + "notebook_task": { + "notebook_path": "/Shared/test", + }, + }, + ] + job_clusters = [ + { + "job_cluster_key": "job_cluster", + "new_cluster": { + "spark_version": "7.3.x-scala2.12", + "node_type_id": "i3.xlarge", + "num_workers": 2, + }, + }, + ] + + jobs_create_named = DatabricksCreateJobsOperator( + task_id="jobs_create_named", tasks=tasks, job_clusters=job_clusters + ) + # [END howto_operator_databricks_jobs_create_named] + + # [START howto_operator_databricks_run_now] + # Example of using the DatabricksRunNowOperator after creating a job with DatabricksCreateJobsOperator. + run_now = DatabricksRunNowOperator( + task_id="run_now", job_id="{{ ti.xcom_pull(task_ids='jobs_create_named') }}" + ) + + jobs_create_named >> run_now + # [END howto_operator_databricks_run_now] + + # [START howto_operator_databricks_json] + # Example of using the JSON parameter to initialize the operator. + new_cluster = { + "spark_version": "9.1.x-scala2.12", + "node_type_id": "r3.xlarge", + "aws_attributes": {"availability": "ON_DEMAND"}, + "num_workers": 8, + } + + notebook_task_params = { + "new_cluster": new_cluster, + "notebook_task": { + "notebook_path": "/Users/airflow@example.com/PrepareData", + }, + } + + notebook_task = DatabricksSubmitRunOperator(task_id="notebook_task", json=notebook_task_params) + # [END howto_operator_databricks_json] + + # [START howto_operator_databricks_named] + # Example of using the named parameters of DatabricksSubmitRunOperator + # to initialize the operator. + spark_jar_task = DatabricksSubmitRunOperator( + task_id="spark_jar_task", + new_cluster=new_cluster, + spark_jar_task={"main_class_name": "com.example.ProcessData"}, + libraries=[{"jar": "dbfs:/lib/etl-0.1.jar"}], + ) + # [END howto_operator_databricks_named] + notebook_task >> spark_jar_task + + from tests.system.utils.watcher import watcher + + # This test needs watcher in order to properly mark success/failure + # when "tearDown" task with trigger rule is part of the DAG + list(dag.tasks) >> watcher() + +from tests.system.utils import get_test_run # noqa: E402 + +# Needed to run the example DAG with pytest (see: tests/system/README.md#run_via_pytest) +
[docs]test_run = get_test_run(dag)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/tests/system/providers/databricks/example_databricks_repos.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/tests/system/providers/databricks/example_databricks_repos.html new file mode 100644 index 00000000000..ae8b813fa43 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/tests/system/providers/databricks/example_databricks_repos.html @@ -0,0 +1,927 @@ + + + + + + + + + + + + tests.system.providers.databricks.example_databricks_repos — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for tests.system.providers.databricks.example_databricks_repos

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import os
+from datetime import datetime
+
+from airflow import DAG
+from airflow.providers.databricks.operators.databricks import DatabricksSubmitRunOperator
+from airflow.providers.databricks.operators.databricks_repos import (
+    DatabricksReposCreateOperator,
+    DatabricksReposDeleteOperator,
+    DatabricksReposUpdateOperator,
+)
+
+
[docs]default_args = { + "owner": "airflow", + "databricks_conn_id": "databricks", +}
+ +
[docs]ENV_ID = os.environ.get("SYSTEM_TESTS_ENV_ID")
+
[docs]DAG_ID = "example_databricks_repos_operator"
+ +with DAG( + dag_id=DAG_ID, + schedule="@daily", + start_date=datetime(2021, 1, 1), + default_args=default_args, + tags=["example"], + catchup=False, +) as dag: + # [START howto_operator_databricks_repo_create] + # Example of creating a Databricks Repo +
[docs] repo_path = "/Repos/user@domain.com/demo-repo"
+ git_url = "https://github.com/test/test" + create_repo = DatabricksReposCreateOperator(task_id="create_repo", repo_path=repo_path, git_url=git_url) + # [END howto_operator_databricks_repo_create] + + # [START howto_operator_databricks_repo_update] + # Example of updating a Databricks Repo to the latest code + repo_path = "/Repos/user@domain.com/demo-repo" + update_repo = DatabricksReposUpdateOperator(task_id="update_repo", repo_path=repo_path, branch="releases") + # [END howto_operator_databricks_repo_update] + + notebook_task_params = { + "new_cluster": { + "spark_version": "9.1.x-scala2.12", + "node_type_id": "r3.xlarge", + "aws_attributes": {"availability": "ON_DEMAND"}, + "num_workers": 8, + }, + "notebook_task": { + "notebook_path": f"{repo_path}/PrepareData", + }, + } + + notebook_task = DatabricksSubmitRunOperator(task_id="notebook_task", json=notebook_task_params) + + # [START howto_operator_databricks_repo_delete] + # Example of deleting a Databricks Repo + repo_path = "/Repos/user@domain.com/demo-repo" + delete_repo = DatabricksReposDeleteOperator(task_id="delete_repo", repo_path=repo_path) + # [END howto_operator_databricks_repo_delete] + + (create_repo >> update_repo >> notebook_task >> delete_repo) + + from tests.system.utils.watcher import watcher + + # This test needs watcher in order to properly mark success/failure + # when "tearDown" task with trigger rule is part of the DAG + list(dag.tasks) >> watcher() + +from tests.system.utils import get_test_run # noqa: E402 + +# Needed to run the example DAG with pytest (see: tests/system/README.md#run_via_pytest) +
[docs]test_run = get_test_run(dag)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/tests/system/providers/databricks/example_databricks_sensors.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/tests/system/providers/databricks/example_databricks_sensors.html new file mode 100644 index 00000000000..4b411a86d91 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/tests/system/providers/databricks/example_databricks_sensors.html @@ -0,0 +1,939 @@ + + + + + + + + + + + + tests.system.providers.databricks.example_databricks_sensors — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for tests.system.providers.databricks.example_databricks_sensors

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import os
+import textwrap
+from datetime import datetime
+
+from airflow import DAG
+from airflow.providers.databricks.sensors.databricks_partition import DatabricksPartitionSensor
+from airflow.providers.databricks.sensors.databricks_sql import DatabricksSqlSensor
+
+# [Env variable to be used from the OS]
+
[docs]ENV_ID = os.environ.get("SYSTEM_TESTS_ENV_ID")
+# [DAG name to be shown on Airflow UI] +
[docs]DAG_ID = "example_databricks_sensor"
+ +with DAG( + dag_id=DAG_ID, + schedule="@daily", + start_date=datetime(2021, 1, 1), + tags=["example"], + catchup=False, +) as dag: + dag.doc_md = textwrap.dedent( + """ + + This is an example DAG which uses the DatabricksSqlSensor + sensor. The example task in the DAG executes the provided + SQL query against the Databricks SQL warehouse and if a + result is returned, the sensor returns True/succeeds. + If no results are returned, the sensor returns False/ + fails. + + """ + ) + # [START howto_sensor_databricks_connection_setup] + # Connection string setup for Databricks workspace. +
[docs] connection_id = "databricks_default"
+ sql_warehouse_name = "Starter Warehouse" + # [END howto_sensor_databricks_connection_setup] + + # [START howto_sensor_databricks_sql] + # Example of using the Databricks SQL Sensor to check existence of data in a table. + sql_sensor = DatabricksSqlSensor( + databricks_conn_id=connection_id, + sql_warehouse_name=sql_warehouse_name, + catalog="hive_metastore", + task_id="sql_sensor_task", + sql="select * from hive_metastore.temp.sample_table_3 limit 1", + timeout=60 * 2, + ) + # [END howto_sensor_databricks_sql] + + # [START howto_sensor_databricks_partition] + # Example of using the Databricks Partition Sensor to check the presence + # of the specified partition(s) in a table. + partition_sensor = DatabricksPartitionSensor( + databricks_conn_id=connection_id, + sql_warehouse_name=sql_warehouse_name, + catalog="hive_metastore", + task_id="partition_sensor_task", + table_name="sample_table_2", + schema="temp", + partitions={"date": "2023-01-03", "name": ["abc", "def"]}, + partition_operator="=", + timeout=60 * 2, + ) + # [END howto_sensor_databricks_partition] + + # Task dependency between the SQL sensor and the partition sensor. + # If the first task(sql_sensor) succeeds, the second task(partition_sensor) + # runs, else all the subsequent DAG tasks and the DAG are marked as failed. + (sql_sensor >> partition_sensor) + + from tests.system.utils.watcher import watcher + + # This example does not need a watcher in order to properly mark success/failure + # since it is a single task, but it is given here as an example for users to + # extend it to their use cases. + # when "tearDown" task with trigger rule is part of the DAG + list(dag.tasks) >> watcher() + +from tests.system.utils import get_test_run # noqa: E402 + +# Needed to run the example DAG with pytest (see: tests/system/README.md#run_via_pytest) +
[docs]test_run = get_test_run(dag)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/tests/system/providers/databricks/example_databricks_sql.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/tests/system/providers/databricks/example_databricks_sql.html new file mode 100644 index 00000000000..8b382065e05 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_modules/tests/system/providers/databricks/example_databricks_sql.html @@ -0,0 +1,962 @@ + + + + + + + + + + + + tests.system.providers.databricks.example_databricks_sql — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for tests.system.providers.databricks.example_databricks_sql

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""
+This is an example DAG which uses the DatabricksSqlOperator
+and DatabricksCopyIntoOperator. The first task creates the table
+and inserts values into it. The second task uses DatabricksSqlOperator
+to select the data. The third task selects the data and stores the
+output of selected data in file path and format specified. The fourth
+task runs the select SQL statement written in the test.sql file. The
+final task using DatabricksCopyIntoOperator loads the data from the
+file_location passed into Delta table.
+"""
+
+from __future__ import annotations
+
+import os
+from datetime import datetime
+
+from airflow import DAG
+from airflow.providers.databricks.operators.databricks_sql import (
+    DatabricksCopyIntoOperator,
+    DatabricksSqlOperator,
+)
+
+
[docs]ENV_ID = os.environ.get("SYSTEM_TESTS_ENV_ID")
+
[docs]DAG_ID = "example_databricks_sql_operator"
+ +with DAG( + dag_id=DAG_ID, + schedule="@daily", + start_date=datetime(2021, 1, 1), + tags=["example"], + catchup=False, +) as dag: +
[docs] connection_id = "my_connection"
+ sql_endpoint_name = "My Endpoint" + + # [START howto_operator_databricks_sql_multiple] + # Example of using the Databricks SQL Operator to perform multiple operations. + create = DatabricksSqlOperator( + databricks_conn_id=connection_id, + sql_endpoint_name=sql_endpoint_name, + task_id="create_and_populate_table", + sql=[ + "drop table if exists default.my_airflow_table", + "create table default.my_airflow_table(id int, v string)", + "insert into default.my_airflow_table values (1, 'test 1'), (2, 'test 2')", + ], + ) + # [END howto_operator_databricks_sql_multiple] + + # [START howto_operator_databricks_sql_select] + # Example of using the Databricks SQL Operator to select data. + select = DatabricksSqlOperator( + databricks_conn_id=connection_id, + sql_endpoint_name=sql_endpoint_name, + task_id="select_data", + sql="select * from default.my_airflow_table", + ) + # [END howto_operator_databricks_sql_select] + + # [START howto_operator_databricks_sql_select_file] + # Example of using the Databricks SQL Operator to select data into a file with JSONL format. + select_into_file = DatabricksSqlOperator( + databricks_conn_id=connection_id, + sql_endpoint_name=sql_endpoint_name, + task_id="select_data_into_file", + sql="select * from default.my_airflow_table", + output_path="/tmp/1.jsonl", + output_format="jsonl", + ) + # [END howto_operator_databricks_sql_select_file] + + # [START howto_operator_databricks_sql_multiple_file] + # Example of using the Databricks SQL Operator to select data. + # SQL statements should be in the file with name test.sql + create_file = DatabricksSqlOperator( + databricks_conn_id=connection_id, + sql_endpoint_name=sql_endpoint_name, + task_id="create_and_populate_from_file", + sql="test.sql", + ) + # [END howto_operator_databricks_sql_multiple_file] + + # [START howto_operator_databricks_copy_into] + # Example of importing data using COPY_INTO SQL command + import_csv = DatabricksCopyIntoOperator( + task_id="import_csv", + databricks_conn_id=connection_id, + sql_endpoint_name=sql_endpoint_name, + table_name="my_table", + file_format="CSV", + file_location="abfss://container@account.dfs.core.windows.net/my-data/csv", + format_options={"header": "true"}, + force_copy=True, + ) + # [END howto_operator_databricks_copy_into] + + (create >> create_file >> import_csv >> select >> select_into_file) + + from tests.system.utils.watcher import watcher + + # This test needs watcher in order to properly mark success/failure + # when "tearDown" task with trigger rule is part of the DAG + list(dag.tasks) >> watcher() + +from tests.system.utils import get_test_run # noqa: E402 + +# Needed to run the example DAG with pytest (see: tests/system/README.md#run_via_pytest) +
[docs]test_run = get_test_run(dag)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/hooks/databricks/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/hooks/databricks/index.rst.txt new file mode 100644 index 00000000000..8308dfea76d --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/hooks/databricks/index.rst.txt @@ -0,0 +1,573 @@ +:py:mod:`airflow.providers.databricks.hooks.databricks` +======================================================= + +.. py:module:: airflow.providers.databricks.hooks.databricks + +.. autoapi-nested-parse:: + + Databricks hook. + + This hook enable the submitting and running of jobs to the Databricks platform. Internally the + operators talk to the + ``api/2.1/jobs/run-now`` + `endpoint _` + or the ``api/2.1/jobs/runs/submit`` + `endpoint `_. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.databricks.hooks.databricks.RunState + airflow.providers.databricks.hooks.databricks.ClusterState + airflow.providers.databricks.hooks.databricks.DatabricksHook + + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.databricks.hooks.databricks.GET_CLUSTER_ENDPOINT + airflow.providers.databricks.hooks.databricks.RESTART_CLUSTER_ENDPOINT + airflow.providers.databricks.hooks.databricks.START_CLUSTER_ENDPOINT + airflow.providers.databricks.hooks.databricks.TERMINATE_CLUSTER_ENDPOINT + airflow.providers.databricks.hooks.databricks.CREATE_ENDPOINT + airflow.providers.databricks.hooks.databricks.RESET_ENDPOINT + airflow.providers.databricks.hooks.databricks.RUN_NOW_ENDPOINT + airflow.providers.databricks.hooks.databricks.SUBMIT_RUN_ENDPOINT + airflow.providers.databricks.hooks.databricks.GET_RUN_ENDPOINT + airflow.providers.databricks.hooks.databricks.CANCEL_RUN_ENDPOINT + airflow.providers.databricks.hooks.databricks.DELETE_RUN_ENDPOINT + airflow.providers.databricks.hooks.databricks.REPAIR_RUN_ENDPOINT + airflow.providers.databricks.hooks.databricks.OUTPUT_RUNS_JOB_ENDPOINT + airflow.providers.databricks.hooks.databricks.CANCEL_ALL_RUNS_ENDPOINT + airflow.providers.databricks.hooks.databricks.INSTALL_LIBS_ENDPOINT + airflow.providers.databricks.hooks.databricks.UNINSTALL_LIBS_ENDPOINT + airflow.providers.databricks.hooks.databricks.LIST_JOBS_ENDPOINT + airflow.providers.databricks.hooks.databricks.LIST_PIPELINES_ENDPOINT + airflow.providers.databricks.hooks.databricks.WORKSPACE_GET_STATUS_ENDPOINT + airflow.providers.databricks.hooks.databricks.SPARK_VERSIONS_ENDPOINT + + +.. py:data:: GET_CLUSTER_ENDPOINT + :value: ('GET', 'api/2.0/clusters/get') + + + +.. py:data:: RESTART_CLUSTER_ENDPOINT + :value: ('POST', 'api/2.0/clusters/restart') + + + +.. py:data:: START_CLUSTER_ENDPOINT + :value: ('POST', 'api/2.0/clusters/start') + + + +.. py:data:: TERMINATE_CLUSTER_ENDPOINT + :value: ('POST', 'api/2.0/clusters/delete') + + + +.. py:data:: CREATE_ENDPOINT + :value: ('POST', 'api/2.1/jobs/create') + + + +.. py:data:: RESET_ENDPOINT + :value: ('POST', 'api/2.1/jobs/reset') + + + +.. py:data:: RUN_NOW_ENDPOINT + :value: ('POST', 'api/2.1/jobs/run-now') + + + +.. py:data:: SUBMIT_RUN_ENDPOINT + :value: ('POST', 'api/2.1/jobs/runs/submit') + + + +.. py:data:: GET_RUN_ENDPOINT + :value: ('GET', 'api/2.1/jobs/runs/get') + + + +.. py:data:: CANCEL_RUN_ENDPOINT + :value: ('POST', 'api/2.1/jobs/runs/cancel') + + + +.. py:data:: DELETE_RUN_ENDPOINT + :value: ('POST', 'api/2.1/jobs/runs/delete') + + + +.. py:data:: REPAIR_RUN_ENDPOINT + :value: ('POST', 'api/2.1/jobs/runs/repair') + + + +.. py:data:: OUTPUT_RUNS_JOB_ENDPOINT + :value: ('GET', 'api/2.1/jobs/runs/get-output') + + + +.. py:data:: CANCEL_ALL_RUNS_ENDPOINT + :value: ('POST', 'api/2.1/jobs/runs/cancel-all') + + + +.. py:data:: INSTALL_LIBS_ENDPOINT + :value: ('POST', 'api/2.0/libraries/install') + + + +.. py:data:: UNINSTALL_LIBS_ENDPOINT + :value: ('POST', 'api/2.0/libraries/uninstall') + + + +.. py:data:: LIST_JOBS_ENDPOINT + :value: ('GET', 'api/2.1/jobs/list') + + + +.. py:data:: LIST_PIPELINES_ENDPOINT + :value: ('GET', 'api/2.0/pipelines') + + + +.. py:data:: WORKSPACE_GET_STATUS_ENDPOINT + :value: ('GET', 'api/2.0/workspace/get-status') + + + +.. py:data:: SPARK_VERSIONS_ENDPOINT + :value: ('GET', 'api/2.0/clusters/spark-versions') + + + +.. py:class:: RunState(life_cycle_state, result_state = '', state_message = '', *args, **kwargs) + + + Utility class for the run state concept of Databricks runs. + + .. py:property:: is_terminal + :type: bool + + True if the current state is a terminal state. + + + .. py:property:: is_successful + :type: bool + + True if the result state is SUCCESS. + + + .. py:attribute:: RUN_LIFE_CYCLE_STATES + :value: ['PENDING', 'RUNNING', 'TERMINATING', 'TERMINATED', 'SKIPPED', 'INTERNAL_ERROR', 'QUEUED'] + + + + .. py:method:: __eq__(other) + + Return self==value. + + + .. py:method:: __repr__() + + Return repr(self). + + + .. py:method:: to_json() + + + .. py:method:: from_json(data) + :classmethod: + + + +.. py:class:: ClusterState(state = '', state_message = '', *args, **kwargs) + + + Utility class for the cluster state concept of Databricks cluster. + + .. py:property:: is_terminal + :type: bool + + True if the current state is a terminal state. + + + .. py:property:: is_running + :type: bool + + True if the current state is running. + + + .. py:attribute:: CLUSTER_LIFE_CYCLE_STATES + :value: ['PENDING', 'RUNNING', 'RESTARTING', 'RESIZING', 'TERMINATING', 'TERMINATED', 'ERROR', 'UNKNOWN'] + + + + .. py:method:: __eq__(other) + + Return self==value. + + + .. py:method:: __repr__() + + Return repr(self). + + + .. py:method:: to_json() + + + .. py:method:: from_json(data) + :classmethod: + + + +.. py:class:: DatabricksHook(databricks_conn_id = BaseDatabricksHook.default_conn_name, timeout_seconds = 180, retry_limit = 3, retry_delay = 1.0, retry_args = None, caller = 'DatabricksHook') + + + Bases: :py:obj:`airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook` + + Interact with Databricks. + + :param databricks_conn_id: Reference to the :ref:`Databricks connection `. + :param timeout_seconds: The amount of time in seconds the requests library + will wait before timing-out. + :param retry_limit: The number of times to retry the connection in case of + service outages. + :param retry_delay: The number of seconds to wait between retries (it + might be a floating point number). + :param retry_args: An optional dictionary with arguments passed to ``tenacity.Retrying`` class. + + .. py:attribute:: hook_name + :value: 'Databricks' + + + + .. py:method:: create_job(json) + + Call the ``api/2.1/jobs/create`` endpoint. + + :param json: The data used in the body of the request to the ``create`` endpoint. + :return: the job_id as an int + + + .. py:method:: reset_job(job_id, json) + + Call the ``api/2.1/jobs/reset`` endpoint. + + :param json: The data used in the new_settings of the request to the ``reset`` endpoint. + + + .. py:method:: run_now(json) + + Call the ``api/2.1/jobs/run-now`` endpoint. + + :param json: The data used in the body of the request to the ``run-now`` endpoint. + :return: the run_id as an int + + + .. py:method:: submit_run(json) + + Call the ``api/2.1/jobs/runs/submit`` endpoint. + + :param json: The data used in the body of the request to the ``submit`` endpoint. + :return: the run_id as an int + + + .. py:method:: list_jobs(limit = 25, expand_tasks = False, job_name = None, page_token = None) + + List the jobs in the Databricks Job Service. + + :param limit: The limit/batch size used to retrieve jobs. + :param expand_tasks: Whether to include task and cluster details in the response. + :param job_name: Optional name of a job to search. + :param page_token: The optional page token pointing at the first first job to return. + :return: A list of jobs. + + + .. py:method:: find_job_id_by_name(job_name) + + Find job id by its name; if there are multiple jobs with the same name, raise AirflowException. + + :param job_name: The name of the job to look up. + :return: The job_id as an int or None if no job was found. + + + .. py:method:: list_pipelines(batch_size = 25, pipeline_name = None, notebook_path = None) + + List the pipelines in Databricks Delta Live Tables. + + :param batch_size: The limit/batch size used to retrieve pipelines. + :param pipeline_name: Optional name of a pipeline to search. Cannot be combined with path. + :param notebook_path: Optional notebook of a pipeline to search. Cannot be combined with name. + :return: A list of pipelines. + + + .. py:method:: find_pipeline_id_by_name(pipeline_name) + + Find pipeline id by its name; if multiple pipelines with the same name, raise AirflowException. + + :param pipeline_name: The name of the pipeline to look up. + :return: The pipeline_id as a GUID string or None if no pipeline was found. + + + .. py:method:: get_run_page_url(run_id) + + Retrieve run_page_url. + + :param run_id: id of the run + :return: URL of the run page + + + .. py:method:: a_get_run_page_url(run_id) + :async: + + Async version of `get_run_page_url()`. + + :param run_id: id of the run + :return: URL of the run page + + + .. py:method:: get_job_id(run_id) + + Retrieve job_id from run_id. + + :param run_id: id of the run + :return: Job id for given Databricks run + + + .. py:method:: get_run_state(run_id) + + Retrieve run state of the run. + + Please note that any Airflow tasks that call the ``get_run_state`` method will result in + failure unless you have enabled xcom pickling. This can be done using the following + environment variable: ``AIRFLOW__CORE__ENABLE_XCOM_PICKLING`` + + If you do not want to enable xcom pickling, use the ``get_run_state_str`` method to get + a string describing state, or ``get_run_state_lifecycle``, ``get_run_state_result``, or + ``get_run_state_message`` to get individual components of the run state. + + :param run_id: id of the run + :return: state of the run + + + .. py:method:: a_get_run_state(run_id) + :async: + + Async version of `get_run_state()`. + + :param run_id: id of the run + :return: state of the run + + + .. py:method:: get_run(run_id) + + Retrieve run information. + + :param run_id: id of the run + :return: state of the run + + + .. py:method:: a_get_run(run_id) + :async: + + Async version of `get_run`. + + :param run_id: id of the run + :return: state of the run + + + .. py:method:: get_run_state_str(run_id) + + Return the string representation of RunState. + + :param run_id: id of the run + :return: string describing run state + + + .. py:method:: get_run_state_lifecycle(run_id) + + Return the lifecycle state of the run. + + :param run_id: id of the run + :return: string with lifecycle state + + + .. py:method:: get_run_state_result(run_id) + + Return the resulting state of the run. + + :param run_id: id of the run + :return: string with resulting state + + + .. py:method:: get_run_state_message(run_id) + + Return the state message for the run. + + :param run_id: id of the run + :return: string with state message + + + .. py:method:: get_run_output(run_id) + + Retrieve run output of the run. + + :param run_id: id of the run + :return: output of the run + + + .. py:method:: cancel_run(run_id) + + Cancel the run. + + :param run_id: id of the run + + + .. py:method:: cancel_all_runs(job_id) + + Cancel all active runs of a job asynchronously. + + :param job_id: The canonical identifier of the job to cancel all runs of + + + .. py:method:: delete_run(run_id) + + Delete a non-active run. + + :param run_id: id of the run + + + .. py:method:: repair_run(json) + + Re-run one or more tasks. + + :param json: repair a job run. + + + .. py:method:: get_latest_repair_id(run_id) + + Get latest repair id if any exist for run_id else None. + + + .. py:method:: get_cluster_state(cluster_id) + + Retrieve run state of the cluster. + + :param cluster_id: id of the cluster + :return: state of the cluster + + + .. py:method:: a_get_cluster_state(cluster_id) + :async: + + Async version of `get_cluster_state`. + + :param cluster_id: id of the cluster + :return: state of the cluster + + + .. py:method:: restart_cluster(json) + + Restarts the cluster. + + :param json: json dictionary containing cluster specification. + + + .. py:method:: start_cluster(json) + + Start the cluster. + + :param json: json dictionary containing cluster specification. + + + .. py:method:: terminate_cluster(json) + + Terminate the cluster. + + :param json: json dictionary containing cluster specification. + + + .. py:method:: install(json) + + Install libraries on the cluster. + + Utility function to call the ``2.0/libraries/install`` endpoint. + + :param json: json dictionary containing cluster_id and an array of library + + + .. py:method:: uninstall(json) + + Uninstall libraries on the cluster. + + Utility function to call the ``2.0/libraries/uninstall`` endpoint. + + :param json: json dictionary containing cluster_id and an array of library + + + .. py:method:: update_repo(repo_id, json) + + Update given Databricks Repos. + + :param repo_id: ID of Databricks Repos + :param json: payload + :return: metadata from update + + + .. py:method:: delete_repo(repo_id) + + Delete given Databricks Repos. + + :param repo_id: ID of Databricks Repos + :return: + + + .. py:method:: create_repo(json) + + Create a Databricks Repos. + + :param json: payload + :return: + + + .. py:method:: get_repo_by_path(path) + + Obtain Repos ID by path. + + :param path: path to a repository + :return: Repos ID if it exists, None if doesn't. + + + .. py:method:: update_job_permission(job_id, json) + + Update databricks job permission. + + :param job_id: job id + :param json: payload + :return: json containing permission specification + + + .. py:method:: test_connection() + + Test the Databricks connectivity from UI. + + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/hooks/databricks_base/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/hooks/databricks_base/index.rst.txt new file mode 100644 index 00000000000..a2a44f6f7bd --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/hooks/databricks_base/index.rst.txt @@ -0,0 +1,160 @@ +:py:mod:`airflow.providers.databricks.hooks.databricks_base` +============================================================ + +.. py:module:: airflow.providers.databricks.hooks.databricks_base + +.. autoapi-nested-parse:: + + Databricks hook. + + This hook enable the submitting and running of jobs to the Databricks platform. Internally the + operators talk to the ``api/2.0/jobs/runs/submit`` + `endpoint `_. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook + airflow.providers.databricks.hooks.databricks_base.BearerAuth + + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.databricks.hooks.databricks_base.AZURE_DEFAULT_AD_ENDPOINT + airflow.providers.databricks.hooks.databricks_base.AZURE_TOKEN_SERVICE_URL + airflow.providers.databricks.hooks.databricks_base.AZURE_METADATA_SERVICE_TOKEN_URL + airflow.providers.databricks.hooks.databricks_base.AZURE_METADATA_SERVICE_INSTANCE_URL + airflow.providers.databricks.hooks.databricks_base.TOKEN_REFRESH_LEAD_TIME + airflow.providers.databricks.hooks.databricks_base.AZURE_MANAGEMENT_ENDPOINT + airflow.providers.databricks.hooks.databricks_base.DEFAULT_DATABRICKS_SCOPE + airflow.providers.databricks.hooks.databricks_base.OIDC_TOKEN_SERVICE_URL + + +.. py:data:: AZURE_DEFAULT_AD_ENDPOINT + :value: 'https://login.microsoftonline.com' + + + +.. py:data:: AZURE_TOKEN_SERVICE_URL + :value: '{}/{}/oauth2/token' + + + +.. py:data:: AZURE_METADATA_SERVICE_TOKEN_URL + :value: 'http://169.254.169.254/metadata/identity/oauth2/token' + + + +.. py:data:: AZURE_METADATA_SERVICE_INSTANCE_URL + :value: 'http://169.254.169.254/metadata/instance' + + + +.. py:data:: TOKEN_REFRESH_LEAD_TIME + :value: 120 + + + +.. py:data:: AZURE_MANAGEMENT_ENDPOINT + :value: 'https://management.core.windows.net/' + + + +.. py:data:: DEFAULT_DATABRICKS_SCOPE + :value: '2ff814a6-3304-4ab8-85cb-cd0e6f879c1d' + + + +.. py:data:: OIDC_TOKEN_SERVICE_URL + :value: '{}/oidc/v1/token' + + + +.. py:class:: BaseDatabricksHook(databricks_conn_id = default_conn_name, timeout_seconds = 180, retry_limit = 3, retry_delay = 1.0, retry_args = None, caller = 'Unknown') + + + Bases: :py:obj:`airflow.hooks.base.BaseHook` + + Base for interaction with Databricks. + + :param databricks_conn_id: Reference to the :ref:`Databricks connection `. + :param timeout_seconds: The amount of time in seconds the requests library + will wait before timing-out. + :param retry_limit: The number of times to retry the connection in case of + service outages. + :param retry_delay: The number of seconds to wait between retries (it + might be a floating point number). + :param retry_args: An optional dictionary with arguments passed to ``tenacity.Retrying`` class. + + .. py:attribute:: conn_name_attr + :type: str + :value: 'databricks_conn_id' + + + + .. py:attribute:: default_conn_name + :value: 'databricks_default' + + + + .. py:attribute:: conn_type + :value: 'databricks' + + + + .. py:attribute:: extra_parameters + :value: ['token', 'host', 'use_azure_managed_identity', 'azure_ad_endpoint', 'azure_resource_id',... + + + + .. py:method:: databricks_conn() + + + .. py:method:: get_conn() + + Return connection for the hook. + + + .. py:method:: user_agent_header() + + + .. py:method:: user_agent_value() + + + .. py:method:: host() + + + .. py:method:: __aenter__() + :async: + + + .. py:method:: __aexit__(*err) + :async: + + + +.. py:class:: BearerAuth(token) + + + Bases: :py:obj:`aiohttp.BasicAuth` + + aiohttp only ships BasicAuth, for Bearer auth we need a subclass of BasicAuth. + + .. py:method:: encode() + + Encode credentials. + + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/hooks/databricks_sql/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/hooks/databricks_sql/index.rst.txt new file mode 100644 index 00000000000..f6a76028b21 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/hooks/databricks_sql/index.rst.txt @@ -0,0 +1,114 @@ +:py:mod:`airflow.providers.databricks.hooks.databricks_sql` +=========================================================== + +.. py:module:: airflow.providers.databricks.hooks.databricks_sql + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.databricks.hooks.databricks_sql.DatabricksSqlHook + + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.databricks.hooks.databricks_sql.LIST_SQL_ENDPOINTS_ENDPOINT + airflow.providers.databricks.hooks.databricks_sql.T + + +.. py:data:: LIST_SQL_ENDPOINTS_ENDPOINT + :value: ('GET', 'api/2.0/sql/endpoints') + + + +.. py:data:: T + + + +.. py:class:: DatabricksSqlHook(databricks_conn_id = BaseDatabricksHook.default_conn_name, http_path = None, sql_endpoint_name = None, session_configuration = None, http_headers = None, catalog = None, schema = None, caller = 'DatabricksSqlHook', return_tuple = False, **kwargs) + + + Bases: :py:obj:`airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook`, :py:obj:`airflow.providers.common.sql.hooks.sql.DbApiHook` + + Hook to interact with Databricks SQL. + + :param databricks_conn_id: Reference to the + :ref:`Databricks connection `. + :param http_path: Optional string specifying HTTP path of Databricks SQL Endpoint or cluster. + If not specified, it should be either specified in the Databricks connection's extra parameters, + or ``sql_endpoint_name`` must be specified. + :param sql_endpoint_name: Optional name of Databricks SQL Endpoint. If not specified, ``http_path`` + must be provided as described above. + :param session_configuration: An optional dictionary of Spark session parameters. Defaults to None. + If not specified, it could be specified in the Databricks connection's extra parameters. + :param http_headers: An optional list of (k, v) pairs that will be set as HTTP headers + on every request + :param catalog: An optional initial catalog to use. Requires DBR version 9.0+ + :param schema: An optional initial schema to use. Requires DBR version 9.0+ + :param return_tuple: Return a ``namedtuple`` object instead of a ``databricks.sql.Row`` object. Default + to False. In a future release of the provider, this will become True by default. This parameter + ensures backward-compatibility during the transition phase to common tuple objects for all hooks based + on DbApiHook. This flag will also be removed in a future release. + :param kwargs: Additional parameters internal to Databricks SQL Connector parameters + + .. py:attribute:: hook_name + :value: 'Databricks SQL' + + + + .. py:method:: get_conn() + + Return a Databricks SQL connection object. + + + .. py:method:: run(sql: str | Iterable[str], autocommit: bool = ..., parameters: Iterable | Mapping[str, Any] | None = ..., handler: None = ..., split_statements: bool = ..., return_last: bool = ...) -> None + run(sql: str | Iterable[str], autocommit: bool = ..., parameters: Iterable | Mapping[str, Any] | None = ..., handler: Callable[[Any], T] = ..., split_statements: bool = ..., return_last: bool = ...) -> tuple | list[tuple] | list[list[tuple] | tuple] | None + + Run a command or a list of commands. + + Pass a list of SQL statements to the SQL parameter to get them to + execute sequentially. + + :param sql: the sql statement to be executed (str) or a list of + sql statements to execute + :param autocommit: What to set the connection's autocommit setting to + before executing the query. Note that currently there is no commit functionality + in Databricks SQL so this flag has no effect. + + :param parameters: The parameters to render the SQL query with. + :param handler: The result handler which is called with the result of each statement. + :param split_statements: Whether to split a single SQL string into statements and run separately + :param return_last: Whether to return result for only last statement or for all after split + :return: return only result of the LAST SQL expression if handler was provided unless return_last + is set to False. + + + .. py:method:: bulk_dump(table, tmp_file) + :abstractmethod: + + Dump a database table into a tab-delimited file. + + :param table: The name of the source table + :param tmp_file: The path of the target file + + + .. py:method:: bulk_load(table, tmp_file) + :abstractmethod: + + Load a tab-delimited file into a database table. + + :param table: The name of the target table + :param tmp_file: The path of the file to load into the table + + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/hooks/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/hooks/index.rst.txt new file mode 100644 index 00000000000..fee1bf444de --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/hooks/index.rst.txt @@ -0,0 +1,17 @@ +:py:mod:`airflow.providers.databricks.hooks` +============================================ + +.. py:module:: airflow.providers.databricks.hooks + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + databricks/index.rst + databricks_base/index.rst + databricks_sql/index.rst + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/index.rst.txt new file mode 100644 index 00000000000..991c5c6e049 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/index.rst.txt @@ -0,0 +1,27 @@ +:py:mod:`airflow.providers.databricks` +====================================== + +.. py:module:: airflow.providers.databricks + + +Subpackages +----------- +.. toctree:: + :titlesonly: + :maxdepth: 3 + + hooks/index.rst + operators/index.rst + sensors/index.rst + triggers/index.rst + utils/index.rst + + +Package Contents +---------------- + +.. py:data:: __version__ + :value: '6.3.0' + + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/operators/databricks/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/operators/databricks/index.rst.txt new file mode 100644 index 00000000000..0b79048a957 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/operators/databricks/index.rst.txt @@ -0,0 +1,559 @@ +:py:mod:`airflow.providers.databricks.operators.databricks` +=========================================================== + +.. py:module:: airflow.providers.databricks.operators.databricks + +.. autoapi-nested-parse:: + + This module contains Databricks operators. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.databricks.operators.databricks.DatabricksJobRunLink + airflow.providers.databricks.operators.databricks.DatabricksCreateJobsOperator + airflow.providers.databricks.operators.databricks.DatabricksSubmitRunOperator + airflow.providers.databricks.operators.databricks.DatabricksSubmitRunDeferrableOperator + airflow.providers.databricks.operators.databricks.DatabricksRunNowOperator + airflow.providers.databricks.operators.databricks.DatabricksRunNowDeferrableOperator + + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.databricks.operators.databricks.DEFER_METHOD_NAME + airflow.providers.databricks.operators.databricks.XCOM_RUN_ID_KEY + airflow.providers.databricks.operators.databricks.XCOM_JOB_ID_KEY + airflow.providers.databricks.operators.databricks.XCOM_RUN_PAGE_URL_KEY + + +.. py:data:: DEFER_METHOD_NAME + :value: 'execute_complete' + + + +.. py:data:: XCOM_RUN_ID_KEY + :value: 'run_id' + + + +.. py:data:: XCOM_JOB_ID_KEY + :value: 'job_id' + + + +.. py:data:: XCOM_RUN_PAGE_URL_KEY + :value: 'run_page_url' + + + +.. py:class:: DatabricksJobRunLink + + + Bases: :py:obj:`airflow.models.BaseOperatorLink` + + Constructs a link to monitor a Databricks Job Run. + + .. py:attribute:: name + :value: 'See Databricks Job Run' + + + + .. py:method:: get_link(operator, *, ti_key) + + Link to external system. + + Note: The old signature of this function was ``(self, operator, dttm: datetime)``. That is still + supported at runtime but is deprecated. + + :param operator: The Airflow operator object this link is associated to. + :param ti_key: TaskInstance ID to return link for. + :return: link to external system + + + +.. py:class:: DatabricksCreateJobsOperator(*, json = None, name = None, tags = None, tasks = None, job_clusters = None, email_notifications = None, webhook_notifications = None, timeout_seconds = None, schedule = None, max_concurrent_runs = None, git_source = None, access_control_list = None, databricks_conn_id = 'databricks_default', polling_period_seconds = 30, databricks_retry_limit = 3, databricks_retry_delay = 1, databricks_retry_args = None, **kwargs) + + + Bases: :py:obj:`airflow.models.BaseOperator` + + Creates (or resets) a Databricks job using the API endpoint. + + .. seealso:: + https://docs.databricks.com/api/workspace/jobs/create + https://docs.databricks.com/api/workspace/jobs/reset + + :param json: A JSON object containing API parameters which will be passed + directly to the ``api/2.1/jobs/create`` endpoint. The other named parameters + (i.e. ``name``, ``tags``, ``tasks``, etc.) to this operator will + be merged with this json dictionary if they are provided. + If there are conflicts during the merge, the named parameters will + take precedence and override the top level json keys. (templated) + + .. seealso:: + For more information about templating see :ref:`concepts:jinja-templating`. + :param name: An optional name for the job. + :param tags: A map of tags associated with the job. + :param tasks: A list of task specifications to be executed by this job. + Array of objects (JobTaskSettings). + :param job_clusters: A list of job cluster specifications that can be shared and reused by + tasks of this job. Array of objects (JobCluster). + :param email_notifications: Object (JobEmailNotifications). + :param webhook_notifications: Object (WebhookNotifications). + :param timeout_seconds: An optional timeout applied to each run of this job. + :param schedule: Object (CronSchedule). + :param max_concurrent_runs: An optional maximum allowed number of concurrent runs of the job. + :param git_source: An optional specification for a remote repository containing the notebooks + used by this job's notebook tasks. Object (GitSource). + :param access_control_list: List of permissions to set on the job. Array of object + (AccessControlRequestForUser) or object (AccessControlRequestForGroup) or object + (AccessControlRequestForServicePrincipal). + + .. seealso:: + This will only be used on create. In order to reset ACL consider using the Databricks + UI. + :param databricks_conn_id: Reference to the + :ref:`Databricks connection `. (templated) + :param polling_period_seconds: Controls the rate which we poll for the result of + this run. By default the operator will poll every 30 seconds. + :param databricks_retry_limit: Amount of times retry if the Databricks backend is + unreachable. Its value must be greater than or equal to 1. + :param databricks_retry_delay: Number of seconds to wait between retries (it + might be a floating point number). + :param databricks_retry_args: An optional dictionary with arguments passed to ``tenacity.Retrying`` class. + + + .. py:attribute:: template_fields + :type: Sequence[str] + :value: ('json', 'databricks_conn_id') + + + + .. py:attribute:: ui_color + :value: '#1CB1C2' + + + + .. py:attribute:: ui_fgcolor + :value: '#fff' + + + + .. py:method:: execute(context) + + Derive when creating an operator. + + Context is the same dictionary used as when rendering jinja templates. + + Refer to get_template_context for more context. + + + +.. py:class:: DatabricksSubmitRunOperator(*, json = None, tasks = None, spark_jar_task = None, notebook_task = None, spark_python_task = None, spark_submit_task = None, pipeline_task = None, dbt_task = None, new_cluster = None, existing_cluster_id = None, libraries = None, run_name = None, timeout_seconds = None, databricks_conn_id = 'databricks_default', polling_period_seconds = 30, databricks_retry_limit = 3, databricks_retry_delay = 1, databricks_retry_args = None, do_xcom_push = True, idempotency_token = None, access_control_list = None, wait_for_termination = True, git_source = None, deferrable = conf.getboolean('operators', 'default_deferrable', fallback=False), **kwargs) + + + Bases: :py:obj:`airflow.models.BaseOperator` + + Submits a Spark job run to Databricks using the api/2.1/jobs/runs/submit API endpoint. + + See: https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunsSubmit + + There are three ways to instantiate this operator. + + .. seealso:: + For more information on how to use this operator, take a look at the guide: + :ref:`howto/operator:DatabricksSubmitRunOperator` + + :param tasks: Array of Objects(RunSubmitTaskSettings) <= 100 items. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunsSubmit + :param json: A JSON object containing API parameters which will be passed + directly to the ``api/2.1/jobs/runs/submit`` endpoint. The other named parameters + (i.e. ``spark_jar_task``, ``notebook_task``..) to this operator will + be merged with this json dictionary if they are provided. + If there are conflicts during the merge, the named parameters will + take precedence and override the top level json keys. (templated) + + .. seealso:: + For more information about templating see :ref:`concepts:jinja-templating`. + https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunsSubmit + :param spark_jar_task: The main class and parameters for the JAR task. Note that + the actual JAR is specified in the ``libraries``. + *EITHER* ``spark_jar_task`` *OR* ``notebook_task`` *OR* ``spark_python_task`` + *OR* ``spark_submit_task`` *OR* ``pipeline_task`` *OR* ``dbt_task`` should be specified. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/2.0/jobs.html#jobssparkjartask + :param notebook_task: The notebook path and parameters for the notebook task. + *EITHER* ``spark_jar_task`` *OR* ``notebook_task`` *OR* ``spark_python_task`` + *OR* ``spark_submit_task`` *OR* ``pipeline_task`` *OR* ``dbt_task`` should be specified. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/2.0/jobs.html#jobsnotebooktask + :param spark_python_task: The python file path and parameters to run the python file with. + *EITHER* ``spark_jar_task`` *OR* ``notebook_task`` *OR* ``spark_python_task`` + *OR* ``spark_submit_task`` *OR* ``pipeline_task`` *OR* ``dbt_task`` should be specified. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/2.0/jobs.html#jobssparkpythontask + :param spark_submit_task: Parameters needed to run a spark-submit command. + *EITHER* ``spark_jar_task`` *OR* ``notebook_task`` *OR* ``spark_python_task`` + *OR* ``spark_submit_task`` *OR* ``pipeline_task`` *OR* ``dbt_task`` should be specified. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/2.0/jobs.html#jobssparksubmittask + :param pipeline_task: Parameters needed to execute a Delta Live Tables pipeline task. + The provided dictionary must contain at least ``pipeline_id`` field! + *EITHER* ``spark_jar_task`` *OR* ``notebook_task`` *OR* ``spark_python_task`` + *OR* ``spark_submit_task`` *OR* ``pipeline_task`` *OR* ``dbt_task`` should be specified. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/2.0/jobs.html#jobspipelinetask + :param dbt_task: Parameters needed to execute a dbt task. + The provided dictionary must contain at least the ``commands`` field and the + ``git_source`` parameter also needs to be set. + *EITHER* ``spark_jar_task`` *OR* ``notebook_task`` *OR* ``spark_python_task`` + *OR* ``spark_submit_task`` *OR* ``pipeline_task`` *OR* ``dbt_task`` should be specified. + This field will be templated. + + :param new_cluster: Specs for a new cluster on which this task will be run. + *EITHER* ``new_cluster`` *OR* ``existing_cluster_id`` should be specified + (except when ``pipeline_task`` is used). + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/2.0/jobs.html#jobsclusterspecnewcluster + :param existing_cluster_id: ID for existing cluster on which to run this task. + *EITHER* ``new_cluster`` *OR* ``existing_cluster_id`` should be specified + (except when ``pipeline_task`` is used). + This field will be templated. + :param libraries: Libraries which this run will use. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/2.0/jobs.html#managedlibrarieslibrary + :param run_name: The run name used for this task. + By default this will be set to the Airflow ``task_id``. This ``task_id`` is a + required parameter of the superclass ``BaseOperator``. + This field will be templated. + :param idempotency_token: an optional token that can be used to guarantee the idempotency of job run + requests. If a run with the provided token already exists, the request does not create a new run but + returns the ID of the existing run instead. This token must have at most 64 characters. + :param access_control_list: optional list of dictionaries representing Access Control List (ACL) for + a given job run. Each dictionary consists of following field - specific subject (``user_name`` for + users, or ``group_name`` for groups), and ``permission_level`` for that subject. See Jobs API + documentation for more details. + :param wait_for_termination: if we should wait for termination of the job run. ``True`` by default. + :param timeout_seconds: The timeout for this run. By default a value of 0 is used + which means to have no timeout. + This field will be templated. + :param databricks_conn_id: Reference to the :ref:`Databricks connection `. + By default and in the common case this will be ``databricks_default``. To use + token based authentication, provide the key ``token`` in the extra field for the + connection and create the key ``host`` and leave the ``host`` field empty. (templated) + :param polling_period_seconds: Controls the rate which we poll for the result of + this run. By default the operator will poll every 30 seconds. + :param databricks_retry_limit: Amount of times retry if the Databricks backend is + unreachable. Its value must be greater than or equal to 1. + :param databricks_retry_delay: Number of seconds to wait between retries (it + might be a floating point number). + :param databricks_retry_args: An optional dictionary with arguments passed to ``tenacity.Retrying`` class. + :param do_xcom_push: Whether we should push run_id and run_page_url to xcom. + :param git_source: Optional specification of a remote git repository from which + supported task types are retrieved. + :param deferrable: Run operator in the deferrable mode. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunsSubmit + + .. py:attribute:: template_fields + :type: Sequence[str] + :value: ('json', 'databricks_conn_id') + + + + .. py:attribute:: template_ext + :type: Sequence[str] + :value: ('.json-tpl',) + + + + .. py:attribute:: ui_color + :value: '#1CB1C2' + + + + .. py:attribute:: ui_fgcolor + :value: '#fff' + + + + .. py:attribute:: operator_extra_links + :value: () + + + + .. py:method:: execute(context) + + Derive when creating an operator. + + Context is the same dictionary used as when rendering jinja templates. + + Refer to get_template_context for more context. + + + .. py:method:: on_kill() + + Override this method to clean up subprocesses when a task instance gets killed. + + Any use of the threading, subprocess or multiprocessing module within an + operator needs to be cleaned up, or it will leave ghost processes behind. + + + .. py:method:: execute_complete(context, event) + + + +.. py:class:: DatabricksSubmitRunDeferrableOperator(*args, **kwargs) + + + Bases: :py:obj:`DatabricksSubmitRunOperator` + + Deferrable version of ``DatabricksSubmitRunOperator``. + + .. py:method:: execute(context) + + Derive when creating an operator. + + Context is the same dictionary used as when rendering jinja templates. + + Refer to get_template_context for more context. + + + +.. py:class:: DatabricksRunNowOperator(*, job_id = None, job_name = None, json = None, notebook_params = None, python_params = None, jar_params = None, spark_submit_params = None, python_named_params = None, idempotency_token = None, databricks_conn_id = 'databricks_default', polling_period_seconds = 30, databricks_retry_limit = 3, databricks_retry_delay = 1, databricks_retry_args = None, do_xcom_push = True, wait_for_termination = True, deferrable = conf.getboolean('operators', 'default_deferrable', fallback=False), repair_run = False, cancel_previous_runs = False, **kwargs) + + + Bases: :py:obj:`airflow.models.BaseOperator` + + Runs an existing Spark job run to Databricks using the api/2.1/jobs/run-now API endpoint. + + See: https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunNow + + There are two ways to instantiate this operator. + + In the first way, you can take the JSON payload that you typically use + to call the ``api/2.1/jobs/run-now`` endpoint and pass it directly + to our ``DatabricksRunNowOperator`` through the ``json`` parameter. + For example :: + + json = { + "job_id": 42, + "notebook_params": {"dry-run": "true", "oldest-time-to-consider": "1457570074236"}, + } + + notebook_run = DatabricksRunNowOperator(task_id="notebook_run", json=json) + + Another way to accomplish the same thing is to use the named parameters + of the ``DatabricksRunNowOperator`` directly. Note that there is exactly + one named parameter for each top level parameter in the ``run-now`` + endpoint. In this method, your code would look like this: :: + + job_id = 42 + + notebook_params = {"dry-run": "true", "oldest-time-to-consider": "1457570074236"} + + python_params = ["douglas adams", "42"] + + jar_params = ["douglas adams", "42"] + + spark_submit_params = ["--class", "org.apache.spark.examples.SparkPi"] + + notebook_run = DatabricksRunNowOperator( + job_id=job_id, + notebook_params=notebook_params, + python_params=python_params, + jar_params=jar_params, + spark_submit_params=spark_submit_params, + ) + + In the case where both the json parameter **AND** the named parameters + are provided, they will be merged together. If there are conflicts during the merge, + the named parameters will take precedence and override the top level ``json`` keys. + + Currently the named parameters that ``DatabricksRunNowOperator`` supports are + - ``job_id`` + - ``job_name`` + - ``json`` + - ``notebook_params`` + - ``python_params`` + - ``python_named_parameters`` + - ``jar_params`` + - ``spark_submit_params`` + - ``idempotency_token`` + - ``repair_run`` + - ``cancel_previous_runs`` + + :param job_id: the job_id of the existing Databricks job. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunNow + :param job_name: the name of the existing Databricks job. + It must exist only one job with the specified name. + ``job_id`` and ``job_name`` are mutually exclusive. + This field will be templated. + :param json: A JSON object containing API parameters which will be passed + directly to the ``api/2.1/jobs/run-now`` endpoint. The other named parameters + (i.e. ``notebook_params``, ``spark_submit_params``..) to this operator will + be merged with this json dictionary if they are provided. + If there are conflicts during the merge, the named parameters will + take precedence and override the top level json keys. (templated) + + .. seealso:: + For more information about templating see :ref:`concepts:jinja-templating`. + https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunNow + :param notebook_params: A dict from keys to values for jobs with notebook task, + e.g. "notebook_params": {"name": "john doe", "age": "35"}. + The map is passed to the notebook and will be accessible through the + dbutils.widgets.get function. See Widgets for more information. + If not specified upon run-now, the triggered run will use the + job's base parameters. notebook_params cannot be + specified in conjunction with jar_params. The json representation + of this field (i.e. {"notebook_params":{"name":"john doe","age":"35"}}) + cannot exceed 10,000 bytes. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/user-guide/notebooks/widgets.html + :param python_params: A list of parameters for jobs with python tasks, + e.g. "python_params": ["john doe", "35"]. + The parameters will be passed to python file as command line parameters. + If specified upon run-now, it would overwrite the parameters specified in job setting. + The json representation of this field (i.e. {"python_params":["john doe","35"]}) + cannot exceed 10,000 bytes. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunNow + :param python_named_params: A list of named parameters for jobs with python wheel tasks, + e.g. "python_named_params": {"name": "john doe", "age": "35"}. + If specified upon run-now, it would overwrite the parameters specified in job setting. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunNow + :param jar_params: A list of parameters for jobs with JAR tasks, + e.g. "jar_params": ["john doe", "35"]. + The parameters will be passed to JAR file as command line parameters. + If specified upon run-now, it would overwrite the parameters specified in + job setting. + The json representation of this field (i.e. {"jar_params":["john doe","35"]}) + cannot exceed 10,000 bytes. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunNow + :param spark_submit_params: A list of parameters for jobs with spark submit task, + e.g. "spark_submit_params": ["--class", "org.apache.spark.examples.SparkPi"]. + The parameters will be passed to spark-submit script as command line parameters. + If specified upon run-now, it would overwrite the parameters specified + in job setting. + The json representation of this field cannot exceed 10,000 bytes. + This field will be templated. + + .. seealso:: + https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunNow + :param idempotency_token: an optional token that can be used to guarantee the idempotency of job run + requests. If a run with the provided token already exists, the request does not create a new run but + returns the ID of the existing run instead. This token must have at most 64 characters. + :param databricks_conn_id: Reference to the :ref:`Databricks connection `. + By default and in the common case this will be ``databricks_default``. To use + token based authentication, provide the key ``token`` in the extra field for the + connection and create the key ``host`` and leave the ``host`` field empty. (templated) + :param polling_period_seconds: Controls the rate which we poll for the result of + this run. By default, the operator will poll every 30 seconds. + :param databricks_retry_limit: Amount of times retry if the Databricks backend is + unreachable. Its value must be greater than or equal to 1. + :param databricks_retry_delay: Number of seconds to wait between retries (it + might be a floating point number). + :param databricks_retry_args: An optional dictionary with arguments passed to ``tenacity.Retrying`` class. + :param do_xcom_push: Whether we should push run_id and run_page_url to xcom. + :param wait_for_termination: if we should wait for termination of the job run. ``True`` by default. + :param deferrable: Run operator in the deferrable mode. + :param repair_run: Repair the databricks run in case of failure. + :param cancel_previous_runs: Cancel all existing running jobs before submitting new one. + + .. py:attribute:: template_fields + :type: Sequence[str] + :value: ('json', 'databricks_conn_id') + + + + .. py:attribute:: template_ext + :type: Sequence[str] + :value: ('.json-tpl',) + + + + .. py:attribute:: ui_color + :value: '#1CB1C2' + + + + .. py:attribute:: ui_fgcolor + :value: '#fff' + + + + .. py:attribute:: operator_extra_links + :value: () + + + + .. py:method:: execute(context) + + Derive when creating an operator. + + Context is the same dictionary used as when rendering jinja templates. + + Refer to get_template_context for more context. + + + .. py:method:: execute_complete(context, event = None) + + + .. py:method:: on_kill() + + Override this method to clean up subprocesses when a task instance gets killed. + + Any use of the threading, subprocess or multiprocessing module within an + operator needs to be cleaned up, or it will leave ghost processes behind. + + + +.. py:class:: DatabricksRunNowDeferrableOperator(*args, **kwargs) + + + Bases: :py:obj:`DatabricksRunNowOperator` + + Deferrable version of ``DatabricksRunNowOperator``. + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/operators/databricks_repos/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/operators/databricks_repos/index.rst.txt new file mode 100644 index 00000000000..83f4d85e607 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/operators/databricks_repos/index.rst.txt @@ -0,0 +1,156 @@ +:py:mod:`airflow.providers.databricks.operators.databricks_repos` +================================================================= + +.. py:module:: airflow.providers.databricks.operators.databricks_repos + +.. autoapi-nested-parse:: + + This module contains Databricks operators. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.databricks.operators.databricks_repos.DatabricksReposCreateOperator + airflow.providers.databricks.operators.databricks_repos.DatabricksReposUpdateOperator + airflow.providers.databricks.operators.databricks_repos.DatabricksReposDeleteOperator + + + + +.. py:class:: DatabricksReposCreateOperator(*, git_url, git_provider = None, branch = None, tag = None, repo_path = None, ignore_existing_repo = False, databricks_conn_id = 'databricks_default', databricks_retry_limit = 3, databricks_retry_delay = 1, **kwargs) + + + Bases: :py:obj:`airflow.models.BaseOperator` + + Creates, and optionally checks out, a Databricks Repo using the POST api/2.0/repos API endpoint. + + See: https://docs.databricks.com/dev-tools/api/latest/repos.html#operation/create-repo + + :param git_url: Required HTTPS URL of a Git repository + :param git_provider: Optional name of Git provider. Must be provided if we can't guess its name from URL. + :param repo_path: optional path for a repository. Must be in the format ``/Repos/{folder}/{repo-name}``. + If not specified, it will be created in the user's directory. + :param branch: optional name of branch to check out. + :param tag: optional name of tag to checkout. + :param ignore_existing_repo: don't throw exception if repository with given path already exists. + :param databricks_conn_id: Reference to the :ref:`Databricks connection `. + By default and in the common case this will be ``databricks_default``. To use + token based authentication, provide the key ``token`` in the extra field for the + connection and create the key ``host`` and leave the ``host`` field empty. (templated) + :param databricks_retry_limit: Amount of times retry if the Databricks backend is + unreachable. Its value must be greater than or equal to 1. + :param databricks_retry_delay: Number of seconds to wait between retries (it + might be a floating point number). + + .. py:attribute:: template_fields + :type: Sequence[str] + :value: ('repo_path', 'tag', 'branch', 'databricks_conn_id') + + + + .. py:attribute:: __git_providers__ + + + + .. py:attribute:: __aws_code_commit_regexp__ + + + + .. py:attribute:: __repos_path_regexp__ + + + + .. py:method:: __detect_repo_provider__(url) + :staticmethod: + + + .. py:method:: execute(context) + + Create a Databricks Repo. + + :param context: context + :return: Repo ID + + + +.. py:class:: DatabricksReposUpdateOperator(*, branch = None, tag = None, repo_id = None, repo_path = None, databricks_conn_id = 'databricks_default', databricks_retry_limit = 3, databricks_retry_delay = 1, **kwargs) + + + Bases: :py:obj:`airflow.models.BaseOperator` + + Updates specified repository to a given branch or tag using the PATCH api/2.0/repos API endpoint. + + See: https://docs.databricks.com/dev-tools/api/latest/repos.html#operation/update-repo + + :param branch: optional name of branch to update to. Should be specified if ``tag`` is omitted + :param tag: optional name of tag to update to. Should be specified if ``branch`` is omitted + :param repo_id: optional ID of existing repository. Should be specified if ``repo_path`` is omitted + :param repo_path: optional path of existing repository. Should be specified if ``repo_id`` is omitted + :param databricks_conn_id: Reference to the :ref:`Databricks connection `. + By default and in the common case this will be ``databricks_default``. To use + token based authentication, provide the key ``token`` in the extra field for the + connection and create the key ``host`` and leave the ``host`` field empty. (templated) + :param databricks_retry_limit: Amount of times retry if the Databricks backend is + unreachable. Its value must be greater than or equal to 1. + :param databricks_retry_delay: Number of seconds to wait between retries (it + might be a floating point number). + + .. py:attribute:: template_fields + :type: Sequence[str] + :value: ('repo_path', 'tag', 'branch', 'databricks_conn_id') + + + + .. py:method:: execute(context) + + Derive when creating an operator. + + Context is the same dictionary used as when rendering jinja templates. + + Refer to get_template_context for more context. + + + +.. py:class:: DatabricksReposDeleteOperator(*, repo_id = None, repo_path = None, databricks_conn_id = 'databricks_default', databricks_retry_limit = 3, databricks_retry_delay = 1, **kwargs) + + + Bases: :py:obj:`airflow.models.BaseOperator` + + Deletes specified repository using the DELETE api/2.0/repos API endpoint. + + See: https://docs.databricks.com/dev-tools/api/latest/repos.html#operation/delete-repo + + :param repo_id: optional ID of existing repository. Should be specified if ``repo_path`` is omitted + :param repo_path: optional path of existing repository. Should be specified if ``repo_id`` is omitted + :param databricks_conn_id: Reference to the :ref:`Databricks connection `. + By default and in the common case this will be ``databricks_default``. To use + token based authentication, provide the key ``token`` in the extra field for the + connection and create the key ``host`` and leave the ``host`` field empty. (templated) + :param databricks_retry_limit: Amount of times retry if the Databricks backend is + unreachable. Its value must be greater than or equal to 1. + :param databricks_retry_delay: Number of seconds to wait between retries (it + might be a floating point number). + + .. py:attribute:: template_fields + :type: Sequence[str] + :value: ('repo_path', 'databricks_conn_id') + + + + .. py:method:: execute(context) + + Derive when creating an operator. + + Context is the same dictionary used as when rendering jinja templates. + + Refer to get_template_context for more context. + + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/operators/databricks_sql/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/operators/databricks_sql/index.rst.txt new file mode 100644 index 00000000000..8c64f2e7717 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/operators/databricks_sql/index.rst.txt @@ -0,0 +1,161 @@ +:py:mod:`airflow.providers.databricks.operators.databricks_sql` +=============================================================== + +.. py:module:: airflow.providers.databricks.operators.databricks_sql + +.. autoapi-nested-parse:: + + This module contains Databricks operators. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.databricks.operators.databricks_sql.DatabricksSqlOperator + airflow.providers.databricks.operators.databricks_sql.DatabricksCopyIntoOperator + + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.databricks.operators.databricks_sql.COPY_INTO_APPROVED_FORMATS + + +.. py:class:: DatabricksSqlOperator(*, databricks_conn_id = DatabricksSqlHook.default_conn_name, http_path = None, sql_endpoint_name = None, session_configuration=None, http_headers = None, catalog = None, schema = None, output_path = None, output_format = 'csv', csv_params = None, client_parameters = None, **kwargs) + + + Bases: :py:obj:`airflow.providers.common.sql.operators.sql.SQLExecuteQueryOperator` + + Executes SQL code in a Databricks SQL endpoint or a Databricks cluster. + + .. seealso:: + For more information on how to use this operator, take a look at the guide: + :ref:`howto/operator:DatabricksSqlOperator` + + :param databricks_conn_id: Reference to + :ref:`Databricks connection id` (templated) + :param http_path: Optional string specifying HTTP path of Databricks SQL Endpoint or cluster. + If not specified, it should be either specified in the Databricks connection's extra parameters, + or ``sql_endpoint_name`` must be specified. + :param sql_endpoint_name: Optional name of Databricks SQL Endpoint. If not specified, ``http_path`` must + be provided as described above. + :param sql: the SQL code to be executed as a single string, or + a list of str (sql statements), or a reference to a template file. (templated) + Template references are recognized by str ending in '.sql' + :param parameters: (optional) the parameters to render the SQL query with. + :param session_configuration: An optional dictionary of Spark session parameters. Defaults to None. + If not specified, it could be specified in the Databricks connection's extra parameters. + :param client_parameters: Additional parameters internal to Databricks SQL Connector parameters + :param http_headers: An optional list of (k, v) pairs that will be set as HTTP headers on every request. + (templated) + :param catalog: An optional initial catalog to use. Requires DBR version 9.0+ (templated) + :param schema: An optional initial schema to use. Requires DBR version 9.0+ (templated) + :param output_path: optional string specifying the file to which write selected data. (templated) + :param output_format: format of output data if ``output_path` is specified. + Possible values are ``csv``, ``json``, ``jsonl``. Default is ``csv``. + :param csv_params: parameters that will be passed to the ``csv.DictWriter`` class used to write CSV data. + + .. py:attribute:: template_fields + :type: Sequence[str] + + + + .. py:attribute:: template_ext + :type: Sequence[str] + :value: ('.sql',) + + + + .. py:attribute:: template_fields_renderers + + + + .. py:attribute:: conn_id_field + :value: 'databricks_conn_id' + + + + .. py:method:: get_db_hook() + + Get the database hook for the connection. + + :return: the database hook object. + + + +.. py:data:: COPY_INTO_APPROVED_FORMATS + :value: ['CSV', 'JSON', 'AVRO', 'ORC', 'PARQUET', 'TEXT', 'BINARYFILE'] + + + +.. py:class:: DatabricksCopyIntoOperator(*, table_name, file_location, file_format, databricks_conn_id = DatabricksSqlHook.default_conn_name, http_path = None, sql_endpoint_name = None, session_configuration=None, http_headers = None, client_parameters = None, catalog = None, schema = None, files = None, pattern = None, expression_list = None, credential = None, storage_credential = None, encryption = None, format_options = None, force_copy = None, copy_options = None, validate = None, **kwargs) + + + Bases: :py:obj:`airflow.models.BaseOperator` + + Executes COPY INTO command in a Databricks SQL endpoint or a Databricks cluster. + + COPY INTO command is constructed from individual pieces, that are described in + `documentation `_. + + .. seealso:: + For more information on how to use this operator, take a look at the guide: + :ref:`howto/operator:DatabricksSqlCopyIntoOperator` + + :param table_name: Required name of the table. (templated) + :param file_location: Required location of files to import. (templated) + :param file_format: Required file format. Supported formats are + ``CSV``, ``JSON``, ``AVRO``, ``ORC``, ``PARQUET``, ``TEXT``, ``BINARYFILE``. + :param databricks_conn_id: Reference to + :ref:`Databricks connection id` (templated) + :param http_path: Optional string specifying HTTP path of Databricks SQL Endpoint or cluster. + If not specified, it should be either specified in the Databricks connection's extra parameters, + or ``sql_endpoint_name`` must be specified. + :param sql_endpoint_name: Optional name of Databricks SQL Endpoint. + If not specified, ``http_path`` must be provided as described above. + :param session_configuration: An optional dictionary of Spark session parameters. Defaults to None. + If not specified, it could be specified in the Databricks connection's extra parameters. + :param http_headers: An optional list of (k, v) pairs that will be set as HTTP headers on every request + :param catalog: An optional initial catalog to use. Requires DBR version 9.0+ + :param schema: An optional initial schema to use. Requires DBR version 9.0+ + :param client_parameters: Additional parameters internal to Databricks SQL Connector parameters + :param files: optional list of files to import. Can't be specified together with ``pattern``. (templated) + :param pattern: optional regex string to match file names to import. + Can't be specified together with ``files``. + :param expression_list: optional string that will be used in the ``SELECT`` expression. + :param credential: optional credential configuration for authentication against a source location. + :param storage_credential: optional Unity Catalog storage credential for destination. + :param encryption: optional encryption configuration for a specified location. + :param format_options: optional dictionary with options specific for a given file format. + :param force_copy: optional bool to control forcing of data import + (could be also specified in ``copy_options``). + :param validate: optional configuration for schema & data validation. ``True`` forces validation + of all rows, integer number - validate only N first rows + :param copy_options: optional dictionary of copy options. Right now only ``force`` option is supported. + + .. py:attribute:: template_fields + :type: Sequence[str] + :value: ('file_location', 'files', 'table_name', 'databricks_conn_id') + + + + .. py:method:: execute(context) + + Derive when creating an operator. + + Context is the same dictionary used as when rendering jinja templates. + + Refer to get_template_context for more context. + + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/operators/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/operators/index.rst.txt new file mode 100644 index 00000000000..c79fe636027 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/operators/index.rst.txt @@ -0,0 +1,17 @@ +:py:mod:`airflow.providers.databricks.operators` +================================================ + +.. py:module:: airflow.providers.databricks.operators + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + databricks/index.rst + databricks_repos/index.rst + databricks_sql/index.rst + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/sensors/databricks_partition/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/sensors/databricks_partition/index.rst.txt new file mode 100644 index 00000000000..e79a078aaad --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/sensors/databricks_partition/index.rst.txt @@ -0,0 +1,76 @@ +:py:mod:`airflow.providers.databricks.sensors.databricks_partition` +=================================================================== + +.. py:module:: airflow.providers.databricks.sensors.databricks_partition + +.. autoapi-nested-parse:: + + This module contains Databricks sensors. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.databricks.sensors.databricks_partition.DatabricksPartitionSensor + + + + +.. py:class:: DatabricksPartitionSensor(*, databricks_conn_id = DatabricksSqlHook.default_conn_name, http_path = None, sql_warehouse_name = None, session_configuration=None, http_headers = None, catalog = '', schema = 'default', table_name, partitions, partition_operator = '=', handler = fetch_all_handler, client_parameters = None, **kwargs) + + + Bases: :py:obj:`airflow.sensors.base.BaseSensorOperator` + + Sensor to detect the presence of table partitions in Databricks. + + :param databricks_conn_id: Reference to :ref:`Databricks + connection id` (templated), defaults to + DatabricksSqlHook.default_conn_name. + :param sql_warehouse_name: Optional name of Databricks SQL warehouse. If not specified, ``http_path`` + must be provided as described below, defaults to None + :param http_path: Optional string specifying HTTP path of Databricks SQL warehouse or All Purpose cluster. + If not specified, it should be either specified in the Databricks connection's + extra parameters, or ``sql_warehouse_name`` must be specified. + :param session_configuration: An optional dictionary of Spark session parameters. If not specified, + it could be specified in the Databricks connection's extra parameters, defaults to None + :param http_headers: An optional list of (k, v) pairs + that will be set as HTTP headers on every request. (templated). + :param catalog: An optional initial catalog to use. + Requires Databricks Runtime version 9.0+ (templated), defaults to "" + :param schema: An optional initial schema to use. + Requires Databricks Runtime version 9.0+ (templated), defaults to "default" + :param table_name: Name of the table to check partitions. + :param partitions: Name of the partitions to check. + Example: {"date": "2023-01-03", "name": ["abc", "def"]} + :param partition_operator: Optional comparison operator for partitions, such as >=. + :param handler: Handler for DbApiHook.run() to return results, defaults to fetch_all_handler + :param client_parameters: Additional parameters internal to Databricks SQL connector parameters. + + .. py:attribute:: template_fields + :type: Sequence[str] + :value: ('databricks_conn_id', 'catalog', 'schema', 'table_name', 'partitions', 'http_headers') + + + + .. py:attribute:: template_ext + :type: Sequence[str] + :value: ('.sql',) + + + + .. py:attribute:: template_fields_renderers + + + + .. py:method:: poke(context) + + Check the table partitions and return the results. + + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/sensors/databricks_sql/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/sensors/databricks_sql/index.rst.txt new file mode 100644 index 00000000000..234d6f82113 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/sensors/databricks_sql/index.rst.txt @@ -0,0 +1,78 @@ +:py:mod:`airflow.providers.databricks.sensors.databricks_sql` +============================================================= + +.. py:module:: airflow.providers.databricks.sensors.databricks_sql + +.. autoapi-nested-parse:: + + This module contains Databricks sensors. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.databricks.sensors.databricks_sql.DatabricksSqlSensor + + + + +.. py:class:: DatabricksSqlSensor(*, databricks_conn_id = DatabricksSqlHook.default_conn_name, http_path = None, sql_warehouse_name = None, session_configuration=None, http_headers = None, catalog = '', schema = 'default', sql, handler = fetch_all_handler, client_parameters = None, **kwargs) + + + Bases: :py:obj:`airflow.sensors.base.BaseSensorOperator` + + Sensor that runs a SQL query on Databricks. + + :param databricks_conn_id: Reference to :ref:`Databricks + connection id` (templated), defaults to + DatabricksSqlHook.default_conn_name. + :param sql_warehouse_name: Optional name of Databricks SQL warehouse. If not specified, ``http_path`` + must be provided as described below, defaults to None + :param http_path: Optional string specifying HTTP path of Databricks SQL warehouse or All Purpose cluster. + If not specified, it should be either specified in the Databricks connection's + extra parameters, or ``sql_warehouse_name`` must be specified. + :param session_configuration: An optional dictionary of Spark session parameters. If not specified, + it could be specified in the Databricks connection's extra parameters, defaults to None + :param http_headers: An optional list of (k, v) pairs + that will be set as HTTP headers on every request. (templated). + :param catalog: An optional initial catalog to use. + Requires Databricks Runtime version 9.0+ (templated), defaults to "" + :param schema: An optional initial schema to use. + Requires Databricks Runtime version 9.0+ (templated), defaults to "default" + :param sql: SQL statement to be executed. + :param handler: Handler for DbApiHook.run() to return results, defaults to fetch_all_handler + :param client_parameters: Additional parameters internal to Databricks SQL connector parameters. + + .. py:attribute:: template_fields + :type: Sequence[str] + :value: ('databricks_conn_id', 'sql', 'catalog', 'schema', 'http_headers') + + + + .. py:attribute:: template_ext + :type: Sequence[str] + :value: ('.sql',) + + + + .. py:attribute:: template_fields_renderers + + + + .. py:method:: hook() + + Creates and returns a DatabricksSqlHook object. + + + .. py:method:: poke(context) + + Sensor poke function to get and return results from the SQL sensor. + + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/sensors/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/sensors/index.rst.txt new file mode 100644 index 00000000000..e09db70821e --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/sensors/index.rst.txt @@ -0,0 +1,16 @@ +:py:mod:`airflow.providers.databricks.sensors` +============================================== + +.. py:module:: airflow.providers.databricks.sensors + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + databricks_partition/index.rst + databricks_sql/index.rst + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/triggers/databricks/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/triggers/databricks/index.rst.txt new file mode 100644 index 00000000000..4314e5eb66e --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/triggers/databricks/index.rst.txt @@ -0,0 +1,61 @@ +:py:mod:`airflow.providers.databricks.triggers.databricks` +========================================================== + +.. py:module:: airflow.providers.databricks.triggers.databricks + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.databricks.triggers.databricks.DatabricksExecutionTrigger + + + + +.. py:class:: DatabricksExecutionTrigger(run_id, databricks_conn_id, polling_period_seconds = 30, retry_limit = 3, retry_delay = 10, retry_args = None, run_page_url = None, repair_run = False) + + + Bases: :py:obj:`airflow.triggers.base.BaseTrigger` + + The trigger handles the logic of async communication with DataBricks API. + + :param run_id: id of the run + :param databricks_conn_id: Reference to the :ref:`Databricks connection `. + :param polling_period_seconds: Controls the rate of the poll for the result of this run. + By default, the trigger will poll every 30 seconds. + :param retry_limit: The number of times to retry the connection in case of service outages. + :param retry_delay: The number of seconds to wait between retries. + :param retry_args: An optional dictionary with arguments passed to ``tenacity.Retrying`` class. + :param run_page_url: The run page url. + + .. py:method:: serialize() + + Return the information needed to reconstruct this Trigger. + + :return: Tuple of (class path, keyword arguments needed to re-instantiate). + + + .. py:method:: run() + :async: + + Run the trigger in an asynchronous context. + + The trigger should yield an Event whenever it wants to fire off + an event, and return None if it is finished. Single-event triggers + should thus yield and then immediately return. + + If it yields, it is likely that it will be resumed very quickly, + but it may not be (e.g. if the workload is being moved to another + triggerer process, or a multi-event trigger was being used for a + single-event task defer). + + In either case, Trigger classes should assume they will be persisted, + and then rely on cleanup() being called when they are no longer needed. + + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/triggers/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/triggers/index.rst.txt new file mode 100644 index 00000000000..f6bfd38a7d1 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/triggers/index.rst.txt @@ -0,0 +1,15 @@ +:py:mod:`airflow.providers.databricks.triggers` +=============================================== + +.. py:module:: airflow.providers.databricks.triggers + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + databricks/index.rst + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/utils/databricks/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/utils/databricks/index.rst.txt new file mode 100644 index 00000000000..05a7919a051 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/utils/databricks/index.rst.txt @@ -0,0 +1,40 @@ +:py:mod:`airflow.providers.databricks.utils.databricks` +======================================================= + +.. py:module:: airflow.providers.databricks.utils.databricks + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.databricks.utils.databricks.normalise_json_content + airflow.providers.databricks.utils.databricks.validate_trigger_event + + + +.. py:function:: normalise_json_content(content, json_path = 'json') + + Normalize content or all values of content if it is a dict to a string. + + The function will throw if content contains non-string or non-numeric non-boolean + types. The reason why we have this function is because the ``self.json`` field + must be a dict with only string values. This is because ``render_template`` will + fail for numerical values. + + The only one exception is when we have boolean values, they can not be converted + to string type because databricks does not understand 'True' or 'False' values. + + +.. py:function:: validate_trigger_event(event) + + Validate correctness of the event received from DatabricksExecutionTrigger. + + See: :class:`~airflow.providers.databricks.triggers.databricks.DatabricksExecutionTrigger`. + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/utils/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/utils/index.rst.txt new file mode 100644 index 00000000000..2417c7c00a2 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/airflow/providers/databricks/utils/index.rst.txt @@ -0,0 +1,15 @@ +:py:mod:`airflow.providers.databricks.utils` +============================================ + +.. py:module:: airflow.providers.databricks.utils + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + databricks/index.rst + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/example_databricks/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/example_databricks/index.rst.txt new file mode 100644 index 00000000000..d373aeb5e64 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/example_databricks/index.rst.txt @@ -0,0 +1,43 @@ +:py:mod:`tests.system.providers.databricks.example_databricks` +============================================================== + +.. py:module:: tests.system.providers.databricks.example_databricks + +.. autoapi-nested-parse:: + + This is an example DAG which uses the DatabricksSubmitRunOperator. + In this example, we create two tasks which execute sequentially. + The first task is to run a notebook at the workspace path "/test" + and the second task is to run a JAR uploaded to DBFS. Both, + tasks use new clusters. + + Because we have set a downstream dependency on the notebook task, + the spark jar task will NOT run until the notebook task completes + successfully. + + The definition of a successful run is if the run has a result_state of "SUCCESS". + For more information about the state of a run refer to + https://docs.databricks.com/api/latest/jobs.html#runstate + + + +Module Contents +--------------- + +.. py:data:: ENV_ID + + + +.. py:data:: DAG_ID + :value: 'example_databricks_operator' + + + +.. py:data:: job + + + +.. py:data:: test_run + + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/example_databricks_repos/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/example_databricks_repos/index.rst.txt new file mode 100644 index 00000000000..7404b433f02 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/example_databricks_repos/index.rst.txt @@ -0,0 +1,31 @@ +:py:mod:`tests.system.providers.databricks.example_databricks_repos` +==================================================================== + +.. py:module:: tests.system.providers.databricks.example_databricks_repos + + +Module Contents +--------------- + +.. py:data:: default_args + + + +.. py:data:: ENV_ID + + + +.. py:data:: DAG_ID + :value: 'example_databricks_repos_operator' + + + +.. py:data:: repo_path + :value: '/Repos/user@domain.com/demo-repo' + + + +.. py:data:: test_run + + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/example_databricks_sensors/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/example_databricks_sensors/index.rst.txt new file mode 100644 index 00000000000..61bb2e65363 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/example_databricks_sensors/index.rst.txt @@ -0,0 +1,27 @@ +:py:mod:`tests.system.providers.databricks.example_databricks_sensors` +====================================================================== + +.. py:module:: tests.system.providers.databricks.example_databricks_sensors + + +Module Contents +--------------- + +.. py:data:: ENV_ID + + + +.. py:data:: DAG_ID + :value: 'example_databricks_sensor' + + + +.. py:data:: connection_id + :value: 'databricks_default' + + + +.. py:data:: test_run + + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/example_databricks_sql/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/example_databricks_sql/index.rst.txt new file mode 100644 index 00000000000..9500d741711 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/example_databricks_sql/index.rst.txt @@ -0,0 +1,39 @@ +:py:mod:`tests.system.providers.databricks.example_databricks_sql` +================================================================== + +.. py:module:: tests.system.providers.databricks.example_databricks_sql + +.. autoapi-nested-parse:: + + This is an example DAG which uses the DatabricksSqlOperator + and DatabricksCopyIntoOperator. The first task creates the table + and inserts values into it. The second task uses DatabricksSqlOperator + to select the data. The third task selects the data and stores the + output of selected data in file path and format specified. The fourth + task runs the select SQL statement written in the test.sql file. The + final task using DatabricksCopyIntoOperator loads the data from the + file_location passed into Delta table. + + + +Module Contents +--------------- + +.. py:data:: ENV_ID + + + +.. py:data:: DAG_ID + :value: 'example_databricks_sql_operator' + + + +.. py:data:: connection_id + :value: 'my_connection' + + + +.. py:data:: test_run + + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/index.rst.txt new file mode 100644 index 00000000000..82c726da3c4 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/_api/tests/system/providers/databricks/index.rst.txt @@ -0,0 +1,18 @@ +:py:mod:`tests.system.providers.databricks` +=========================================== + +.. py:module:: tests.system.providers.databricks + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + example_databricks/index.rst + example_databricks_repos/index.rst + example_databricks_sensors/index.rst + example_databricks_sql/index.rst + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/changelog.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/changelog.rst.txt new file mode 100644 index 00000000000..87771d0f519 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/changelog.rst.txt @@ -0,0 +1,25 @@ + + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + .. NOTE! THIS FILE IS AUTOMATICALLY GENERATED AND WILL BE + OVERWRITTEN WHEN PREPARING PACKAGES. + + .. IF YOU WANT TO MODIFY THIS FILE, YOU SHOULD MODIFY THE TEMPLATE + `PROVIDER_CHANGELOG_TEMPLATE.rst.jinja2` IN the `dev/breeze/src/airflow_breeze/templates` DIRECTORY + +.. include:: ../../airflow/providers/databricks/CHANGELOG.rst diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/commits.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/commits.rst.txt new file mode 100644 index 00000000000..5a750f216cb --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/commits.rst.txt @@ -0,0 +1,697 @@ + + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + .. NOTE! THIS FILE IS AUTOMATICALLY GENERATED AND WILL BE + OVERWRITTEN WHEN PREPARING PACKAGES. + + .. IF YOU WANT TO MODIFY THIS FILE, YOU SHOULD MODIFY THE TEMPLATE + `PROVIDER_COMMITS_TEMPLATE.rst.jinja2` IN the `dev/breeze/src/airflow_breeze/templates` DIRECTORY + + .. THE REMAINDER OF THE FILE IS AUTOMATICALLY GENERATED. IT WILL BE OVERWRITTEN AT RELEASE TIME! + +Package apache-airflow-providers-databricks +------------------------------------------------------ + +`Databricks `__ + + +This is detailed commit list of changes for versions provider package: ``databricks``. +For high-level changelog, see :doc:`package information including changelog `. + + + +6.3.0 +..... + +Latest change: 2024-04-16 + +================================================================================================= =========== ====================================================================================================== +Commit Committed Subject +================================================================================================= =========== ====================================================================================================== +`66df296a6e `_ 2024-04-16 ``[FIX] typo in parameter (#39050)`` +`629545bea2 `_ 2024-04-14 ``Adds job_id as path param in update permission (#38962)`` +`f9dcc82fb6 `_ 2024-04-13 ``Prepare docs 1st wave (RC2) April 2024 (#38995)`` +`4a669fb1a9 `_ 2024-04-11 ``Remove extra slash from update permission endpoint (#38918)`` +`5fa80b6aea `_ 2024-04-10 ``Prepare docs 1st wave (RC1) April 2024 (#38863)`` +`6f21f7dc9b `_ 2024-04-10 ``Update ACL during job reset (#38741)`` +`4e6d3fa4cf `_ 2024-04-08 ``Add cancel_previous_run to DatabricksRunNowOperator (#38702)`` +`39b684d91a `_ 2024-04-01 ``add repair_run support to DatabricksRunNowOperator in deferrable mode (#38619)`` +`c74947a69d `_ 2024-03-22 ``refactor(databricks): remove redundant else block (#38397)`` +`b5b972a106 `_ 2024-03-18 ``Update yanked versions in providers changelogs (#38262)`` +`0a74928894 `_ 2024-03-18 ``Bump ruff to 0.3.3 (#38240)`` +`aa75fbb2b8 `_ 2024-03-16 ``Restore Python 3.12 support for Databricks (#38207)`` +`4742fc0ea5 `_ 2024-03-15 ``Rename 'DatabricksSqlOperator''s fields' names to comply with templated fields validation (#38052)`` +`8fc984873a `_ 2024-03-12 ``Exclude Python 3.12 for Databricks provider (#38070)`` +`83316b8158 `_ 2024-03-04 ``Prepare docs 1st wave (RC1) March 2024 (#37876)`` +`14d9bff3ad `_ 2024-02-24 ``update pre-commit (#37665)`` +`5a0be392e6 `_ 2024-02-16 ``Add comment about versions updated by release manager (#37488)`` +`e346253760 `_ 2024-02-15 ``Fix remaining D401 checks (#37434)`` +================================================================================================= =========== ====================================================================================================== + +6.2.0 +..... + +Latest change: 2024-02-12 + +================================================================================================= =========== ================================================================================== +Commit Committed Subject +================================================================================================= =========== ================================================================================== +`bfb054e9e8 `_ 2024-02-12 ``Prepare docs 1st wave of Providers February 2024 (#37326)`` +`78294c24e2 `_ 2024-02-11 ``Get rid of pytest-httpx as dependency (#37334)`` +`0c4210af62 `_ 2024-01-31 ``Bump aiohttp min version to avoid CVE-2024-23829 and CVE-2024-23334 (#37110)`` +`6d748c923b `_ 2024-01-30 ``Update DatabricksSqlOperator to work with namedtuple (#37025)`` +`dec2662190 `_ 2024-01-30 ``feat: Switch all class, functions, methods deprecations to decorators (#36876)`` +================================================================================================= =========== ================================================================================== + +6.1.0 +..... + +Latest change: 2024-01-26 + +================================================================================================= =========== ====================================================================================================================== +Commit Committed Subject +================================================================================================= =========== ====================================================================================================================== +`cead3da4a6 `_ 2024-01-26 ``Add docs for RC2 wave of providers for 2nd round of Jan 2024 (#37019)`` +`0b680c9492 `_ 2024-01-26 ``Revert "Provide the logger_name param in providers hooks in order to override the logger name (#36675)" (#37015)`` +`c0f7601391 `_ 2024-01-23 ``Rename columns to valid namedtuple attributes + ensure Row.fields are retrieved as tuple (#36949)`` +`347373986c `_ 2024-01-23 ``check status before DatabricksSubmitRunOperator & DatabricksSubmitRunOperator executes in deferrable mode (#36862)`` +`2b4da0101f `_ 2024-01-22 ``Prepare docs 2nd wave of Providers January 2024 (#36945)`` +`13b0930bf4 `_ 2024-01-17 ``Fix databricks_sql hook query failing on empty result for return_tuple (#36827)`` +`574102fd29 `_ 2024-01-11 ``[FEAT] adds repair run functionality for databricks (#36601)`` +`c439ab87c4 `_ 2024-01-10 ``Standardize airflow build process and switch to Hatchling build backend (#36537)`` +`6bd450da1e `_ 2024-01-10 ``Provide the logger_name param in providers hooks in order to override the logger name (#36675)`` +`f7b663d9af `_ 2024-01-07 ``Run mypy checks for full packages in CI (#36638)`` +`19ebcac239 `_ 2024-01-07 ``Prepare docs 1st wave of Providers January 2024 (#36640)`` +`6937ae7647 `_ 2023-12-30 ``Speed up autocompletion of Breeze by simplifying provider state (#36499)`` +================================================================================================= =========== ====================================================================================================================== + +6.0.0 +..... + +Latest change: 2023-12-23 + +================================================================================================= =========== ================================================================================================ +Commit Committed Subject +================================================================================================= =========== ================================================================================================ +`77b563bfc5 `_ 2023-12-23 ``Update version and added breaking change for databricks provider (#36382)`` +`b15d5578da `_ 2023-12-23 ``Re-apply updated version numbers to 2nd wave of providers in December (#36380)`` +`f5883d6e7b `_ 2023-12-23 ``Prepare 2nd wave of providers in December (#36373)`` +`5fe5d31a46 `_ 2023-12-22 ``Return common data structure in DBApi derived classes`` +`322aa649ed `_ 2023-12-21 ``fix typos in DatabricksSubmitRunOperator (#36248)`` +`e9ba37bb58 `_ 2023-12-17 ``Add code snippet formatting in docstrings via Ruff (#36262)`` +`64931b1a65 `_ 2023-12-12 ``Prepare docs 1st wave of Providers December 2023 RC2 (#36190)`` +`36010f6d0e `_ 2023-12-11 ``Fix: Implement support for 'fetchone()' in the ODBCHook and the Databricks SQL Hook (#36161)`` +`999b70178a `_ 2023-12-08 ``Prepare docs 1st wave of Providers December 2023 (#36112)`` +`d0918d77ee `_ 2023-12-07 ``Bump minimum Airflow version in providers to Airflow 2.6.0 (#36017)`` +================================================================================================= =========== ================================================================================================ + +5.0.1 +..... + +Latest change: 2023-11-24 + +================================================================================================= =========== ==================================================================================================== +Commit Committed Subject +================================================================================================= =========== ==================================================================================================== +`0b23d5601c `_ 2023-11-24 ``Prepare docs 2nd wave of Providers November 2023 (#35836)`` +`99534e47f3 `_ 2023-11-19 ``Use reproducible builds for provider packages (#35693)`` +`064fc2b775 `_ 2023-11-17 ``Make pyodbc.Row and databricks.Row JSON-serializable via new 'make_serializable' method (#32319)`` +`99df205f42 `_ 2023-11-16 ``Fix and reapply templates for provider documentation (#35686)`` +================================================================================================= =========== ==================================================================================================== + +5.0.0 +..... + +Latest change: 2023-11-08 + +================================================================================================= =========== ========================================================================================= +Commit Committed Subject +================================================================================================= =========== ========================================================================================= +`1b059c57d6 `_ 2023-11-08 ``Prepare docs 1st wave of Providers November 2023 (#35537)`` +`10bac853d2 `_ 2023-11-03 ``Remove offset-based pagination from 'list_jobs' function in 'DatabricksHook' (#34926)`` +================================================================================================= =========== ========================================================================================= + +4.7.0 +..... + +Latest change: 2023-10-28 + +================================================================================================= =========== ========================================================================= +Commit Committed Subject +================================================================================================= =========== ========================================================================= +`d1c58d86de `_ 2023-10-28 ``Prepare docs 3rd wave of Providers October 2023 - FIX (#35233)`` +`3592ff4046 `_ 2023-10-28 ``Prepare docs 3rd wave of Providers October 2023 (#35187)`` +`a8784e3c35 `_ 2023-10-28 ``Add operator to create jobs in Databricks (#35156)`` +`dd7ba3cae1 `_ 2023-10-19 ``Pre-upgrade 'ruff==0.0.292' changes in providers (#35053)`` +`7a93b19138 `_ 2023-10-16 ``D401 Support - Providers: DaskExecutor to Github (Inclusive) (#34935)`` +================================================================================================= =========== ========================================================================= + +4.6.0 +..... + +Latest change: 2023-10-13 + +================================================================================================= =========== ================================================================================================== +Commit Committed Subject +================================================================================================= =========== ================================================================================================== +`e9987d5059 `_ 2023-10-13 ``Prepare docs 1st wave of Providers in October 2023 (#34916)`` +`946b539f0d `_ 2023-10-12 ``Add 'DatabricksHook' ClusterState (#34643)`` +`0c8e30e43b `_ 2023-10-05 ``Bump min airflow version of providers (#34728)`` +`7ebf4220c9 `_ 2023-09-28 ``Refactor usage of str() in providers (#34320)`` +`a1ef232230 `_ 2023-09-25 ``Use aiohttp.BasicAuth instead of HTTPBasicAuth for aiohttp session in databricks hook (#34590)`` +`f26fa6d602 `_ 2023-09-22 ``Respect 'soft_fail' parameter in 'DatabricksSqlSensor' (#34544)`` +`3813ed69c7 `_ 2023-09-22 ``Respect 'soft_fail' argument when running DatabricksPartitionSensor (#34517)`` +`966c2bce9f `_ 2023-09-21 ``Decode response in f-string (#34518)`` +`dfec053371 `_ 2023-09-12 ``Update 'list_jobs' function in 'DatabricksHook' to token-based pagination (#33472)`` +================================================================================================= =========== ================================================================================================== + +4.5.0 +..... + +Latest change: 2023-09-08 + +================================================================================================= =========== =================================================================================================== +Commit Committed Subject +================================================================================================= =========== =================================================================================================== +`21990ed894 `_ 2023-09-08 ``Prepare docs for 09 2023 - 1st wave of Providers (#34201)`` +`c45617c4d5 `_ 2023-09-07 ``allow DatabricksSubmitRunOperator to accept a pipeline name for a pipeline_task (#32903)`` +`55976af32e `_ 2023-08-31 ``Replace sequence concatination by unpacking in Airflow providers (#33933)`` +`f7a005db8c `_ 2023-08-30 ``Add "QUEUED" to RUN_LIFE_CYCLE_STATES following deployement of … (#33886)`` +`9d8c77e447 `_ 2023-08-27 ``Improve modules import in Airflow providers by some of them into a type-checking block (#33754)`` +`b11525702c `_ 2023-08-26 ``Use literal dict instead of calling dict() in providers (#33761)`` +`c90eec9365 `_ 2023-08-26 ``Use f-string instead of in Airflow providers (#33752)`` +================================================================================================= =========== =================================================================================================== + +4.4.0 +..... + +Latest change: 2023-08-26 + +================================================================================================= =========== ======================================================================= +Commit Committed Subject +================================================================================================= =========== ======================================================================= +`c077d19060 `_ 2023-08-26 ``Prepare docs for Aug 2023 3rd wave of Providers (#33730)`` +`dc47c460dc `_ 2023-08-24 ``Update docs in databricks.py - we use 2.1 now (#32340)`` +`4154cc04ce `_ 2023-08-24 ``Do not create lists we don't need (#33519)`` +`2dbb963324 `_ 2023-08-24 ``Refactor: Improve detection of duplicates and list sorting (#33675)`` +`1cdd82391e `_ 2023-08-21 ``Simplify conditions on len() in other providers (#33569)`` +`a91ee7ac2f `_ 2023-08-20 ``Refactor: Simplify code in smaller providers (#33234)`` +`8bf53dd554 `_ 2023-08-14 ``Add Service Principal OAuth for Databricks. (#33005)`` +`5f8f25b34c `_ 2023-08-11 ``Ecldude databrick connector 2.9.0 due to a bug (#33311)`` +================================================================================================= =========== ======================================================================= + +4.3.3 +..... + +Latest change: 2023-08-11 + +================================================================================================= =========== ========================================================================== +Commit Committed Subject +================================================================================================= =========== ========================================================================== +`b5a4d36383 `_ 2023-08-11 ``Prepare docs for Aug 2023 2nd wave of Providers (#33291)`` +`9736143468 `_ 2023-08-07 ``Add a new parameter to SQL operators to specify conn id field (#30784)`` +================================================================================================= =========== ========================================================================== + +4.3.2 +..... + +Latest change: 2023-07-29 + +================================================================================================= =========== ========================================================================================================================== +Commit Committed Subject +================================================================================================= =========== ========================================================================================================================== +`d06b7af69a `_ 2023-07-29 ``Prepare docs for July 2023 3rd wave of Providers (#32875)`` +`58e21c66fd `_ 2023-07-25 ``fix(providers/databricks): remove the execute method from to-be-deprecated DatabricksRunNowDeferrableOperator (#32806)`` +`6313e52932 `_ 2023-07-24 ``Add missing execute_complete method for 'DatabricksRunNowOperator' (#32689)`` +`60c49ab2df `_ 2023-07-19 ``Add more accurate typing for DbApiHook.run method (#31846)`` +================================================================================================= =========== ========================================================================================================================== + +4.3.1 +..... + +Latest change: 2023-07-06 + +================================================================================================= =========== =============================================================================================== +Commit Committed Subject +================================================================================================= =========== =============================================================================================== +`225e3041d2 `_ 2023-07-06 ``Prepare docs for July 2023 wave of Providers (RC2) (#32381)`` +`3878fe6fab `_ 2023-07-05 ``Remove spurious headers for provider changelogs (#32373)`` +`cb4927a018 `_ 2023-07-05 ``Prepare docs for July 2023 wave of Providers (#32298)`` +`f8593503cb `_ 2023-07-05 ``Add default_deferrable config (#31712)`` +`6b4350e89c `_ 2023-06-29 ``Modify 'template_fields' of 'DatabricksSqlOperator' to support parent class fields (#32253)`` +`d1aa509bbd `_ 2023-06-28 ``D205 Support - Providers: Databricks to Github (inclusive) (#32243)`` +`09d4718d3a `_ 2023-06-27 ``Improve provider documentation and README structure (#32125)`` +================================================================================================= =========== =============================================================================================== + +4.3.0 +..... + +Latest change: 2023-06-20 + +================================================================================================= =========== =========================================================================================== +Commit Committed Subject +================================================================================================= =========== =========================================================================================== +`79bcc2e668 `_ 2023-06-20 ``Prepare RC1 docs for June 2023 wave of Providers (#32001)`` +`8b146152d6 `_ 2023-06-20 ``Add note about dropping Python 3.7 for providers (#32015)`` +`69bc90b824 `_ 2023-06-19 ``Fix type annotation (#31888)`` +`66299338eb `_ 2023-06-18 ``add a return when the event is yielded in a loop to stop the execution (#31985)`` +`7b096483fa `_ 2023-06-14 ``Making Databricks run related multi-query string in one session again (#31898) (#31899)`` +`049c6184b7 `_ 2023-06-08 ``Fix Databricks SQL operator serialization (#31780)`` +`9276310a43 `_ 2023-06-05 ``Improve docstrings in providers (#31681)`` +`86b5ba2802 `_ 2023-06-04 ``Remove return statement after yield from triggers class (#31703)`` +`dc5bf3fd02 `_ 2023-06-02 ``Add discoverability for triggers in provider.yaml (#31576)`` +`a59076eaee `_ 2023-06-02 ``Add D400 pydocstyle check - Providers (#31427)`` +`9fa75aaf7a `_ 2023-05-29 ``Remove Python 3.7 support (#30963)`` +================================================================================================= =========== =========================================================================================== + +4.2.0 +..... + +Latest change: 2023-05-19 + +================================================================================================= =========== ====================================================================================== +Commit Committed Subject +================================================================================================= =========== ====================================================================================== +`45548b9451 `_ 2023-05-19 ``Prepare RC2 docs for May 2023 wave of Providers (#31416)`` +`abea189022 `_ 2023-05-18 ``Use '__version__' in providers not 'version' (#31393)`` +`f5aed58d9f `_ 2023-05-18 ``Fixing circular import error in providers caused by airflow version check (#31379)`` +`d9ff55cf6d `_ 2023-05-16 ``Prepare docs for May 2023 wave of Providers (#31252)`` +`fdc7a31aeb `_ 2023-05-13 ``Add 'DatabricksPartitionSensor' (#30980)`` +`edd7133a13 `_ 2023-05-09 ``Add conditional output processing in SQL operators (#31136)`` +`3df0be0f6f `_ 2023-05-08 ``Add cancel all runs functionality to Databricks hook (#31038)`` +`ac46902154 `_ 2023-05-04 ``Move TaskInstanceKey to a separate file (#31033)`` +`0a30706aa7 `_ 2023-05-03 ``Use 'AirflowProviderDeprecationWarning' in providers (#30975)`` +`eef5bc7f16 `_ 2023-05-03 ``Add full automation for min Airflow version for providers (#30994)`` +`a7eb32a5b2 `_ 2023-04-30 ``Bump minimum Airflow version in providers (#30917)`` +`9409446097 `_ 2023-04-24 ``Add cli cmd to list the provider trigger info (#30822)`` +`ecb9a9ea78 `_ 2023-04-23 ``Add retry param in databrics async operator (#30744)`` +`9bebf85e24 `_ 2023-04-22 ``Add repair job functionality to databricks hook (#30786)`` +`7d02277ae1 `_ 2023-04-22 ``Deprecate databricks async operator (#30761)`` +================================================================================================= =========== ====================================================================================== + +4.1.0 +..... + +Latest change: 2023-04-21 + +================================================================================================= =========== ========================================================================= +Commit Committed Subject +================================================================================================= =========== ========================================================================= +`e46ce78b66 `_ 2023-04-21 ``Prepare docs for adhoc release of providers (#30787)`` +`37cf0506b5 `_ 2023-04-14 ``Add delete inactive run functionality to databricks provider (#30646)`` +`1e311cf036 `_ 2023-04-11 ``Databricks SQL sensor (#30477)`` +`d23a3bbed8 `_ 2023-04-04 ``Add mechanism to suspend providers (#30422)`` +================================================================================================= =========== ========================================================================= + +4.0.1 +..... + +Latest change: 2023-04-02 + +================================================================================================= =========== ============================================================ +Commit Committed Subject +================================================================================================= =========== ============================================================ +`55dbf1ff1f `_ 2023-04-02 ``Prepare docs for April 2023 wave of Providers (#30378)`` +`c3867781e0 `_ 2023-03-08 ``adding trigger info to provider yaml (#29950)`` +`c405ecb63e `_ 2023-03-07 ``DatabricksSubmitRunOperator to support taskflow (#29840)`` +================================================================================================= =========== ============================================================ + +4.0.0 +..... + +Latest change: 2022-11-26 + +================================================================================================= =========== ============================================================================== +Commit Committed Subject +================================================================================================= =========== ============================================================================== +`25bdbc8e67 `_ 2022-11-26 ``Updated docs for RC3 wave of providers (#27937)`` +`db5375bea7 `_ 2022-11-26 ``Fixing the behaviours of SQL Hooks and Operators finally (#27912)`` +`2e20e9f7eb `_ 2022-11-24 ``Prepare for follow-up relase for November providers (#27774)`` +`80c327bd3b `_ 2022-11-24 ``Bump common.sql provider to 1.3.1 (#27888)`` +`ea306c9462 `_ 2022-11-24 ``Fix errors in Databricks SQL operator introduced when refactoring (#27854)`` +`a343bba1e3 `_ 2022-11-23 ``Fix templating fields and do_xcom_push in DatabricksSQLOperator (#27868)`` +================================================================================================= =========== ============================================================================== + +3.4.0 +..... + +Latest change: 2022-11-15 + +================================================================================================= =========== ========================================================================= +Commit Committed Subject +================================================================================================= =========== ========================================================================= +`12c3c39d1a `_ 2022-11-15 ``pRepare docs for November 2022 wave of Providers (#27613)`` +`00af5c007e `_ 2022-11-14 ``Replace urlparse with urlsplit (#27389)`` +`eb06c65556 `_ 2022-11-11 ``Use new job search API for triggering Databricks job by name (#27446)`` +`9ab1a6a3e7 `_ 2022-10-27 ``Update old style typing (#26872)`` +`78b8ea2f22 `_ 2022-10-24 ``Move min airflow version to 2.3.0 for all providers (#27196)`` +`2a34dc9e84 `_ 2022-10-23 ``Enable string normalization in python formatting - providers (#27205)`` +`ecd4d6654f `_ 2022-10-18 ``Add SQLExecuteQueryOperator (#25717)`` +================================================================================================= =========== ========================================================================= + +3.3.0 +..... + +Latest change: 2022-09-28 + +================================================================================================= =========== ==================================================================================== +Commit Committed Subject +================================================================================================= =========== ==================================================================================== +`f8db64c35c `_ 2022-09-28 ``Update docs for September Provider's release (#26731)`` +`89e44c46ad `_ 2022-09-27 ``Remove duplicated connection-type within the provider (#26628)`` +`06acf40a43 `_ 2022-09-13 ``Apply PEP-563 (Postponed Evaluation of Annotations) to non-core airflow (#26289)`` +`5066844513 `_ 2022-09-09 ``D400 first line should end with period batch02 (#25268)`` +`25a9c6a905 `_ 2022-08-26 ``DatabricksSubmitRunOperator dbt task support (#25623)`` +`9535ec0bba `_ 2022-08-22 ``Databricks: fix provider name in the User-Agent string (#25873)`` +`ca9229b6fe `_ 2022-08-18 ``Add common-sql lower bound for common-sql (#25789)`` +================================================================================================= =========== ==================================================================================== + +3.2.0 +..... + +Latest change: 2022-08-15 + +================================================================================================= =========== =================================================================================== +Commit Committed Subject +================================================================================================= =========== =================================================================================== +`7d0525a55b `_ 2022-08-15 ``Prepare documentation for RC4 release of providers (#25720)`` +`4d32f61fd0 `_ 2022-08-12 ``Databricks: Fix provider for Airflow 2.2.x (#25674)`` +`e5ac6c7cfb `_ 2022-08-10 ``Prepare docs for new providers release (August 2022) (#25618)`` +`52f2f5bfa8 `_ 2022-08-07 ``Databricks: update user-agent string (#25578)`` +`0255a0a5e7 `_ 2022-08-04 ``Do not convert boolean values to string in deep_string_coerce function (#25394)`` +`679a85325a `_ 2022-08-03 ``Correctly handle output of the failed tasks (#25427)`` +`82f842ffc5 `_ 2022-07-28 ``updated documentation for databricks operator (#24599)`` +`54a8c4fd2a `_ 2022-07-27 ``More improvements in the Databricks operators (#25260)`` +`7438707747 `_ 2022-07-26 ``Improved telemetry for Databricks provider (#25115)`` +`df00436569 `_ 2022-07-22 ``Unify DbApiHook.run() method with the methods which override it (#23971)`` +`2f70daf5ac `_ 2022-07-18 ``Databricks: fix test_connection implementation (#25114)`` +================================================================================================= =========== =================================================================================== + +3.1.0 +..... + +Latest change: 2022-07-13 + +================================================================================================= =========== ============================================================================= +Commit Committed Subject +================================================================================================= =========== ============================================================================= +`d2459a241b `_ 2022-07-13 ``Add documentation for July 2022 Provider's release (#25030)`` +`8dfe7bf5ff `_ 2022-07-11 ``Added databricks_conn_id as templated field (#24945)`` +`acaa0635c8 `_ 2022-07-08 ``Automatically detect if non-lazy logging interpolation is used (#24910)`` +`46bbfdade0 `_ 2022-07-07 ``Move all SQL classes to common-sql provider (#24836)`` +`96b01a8012 `_ 2022-07-05 ``Remove "bad characters" from our codebase (#24841)`` +`0de31bd73a `_ 2022-06-29 ``Move provider dependencies to inside provider folders (#24672)`` +`510a6bab45 `_ 2022-06-28 ``Remove 'hook-class-names' from provider.yaml (#24702)`` +`ed37c3a0e8 `_ 2022-06-28 ``Add 'test_connection' method to Databricks hook (#24617)`` +`9c59831ee7 `_ 2022-06-21 ``Update providers to use functools compat for ''cached_property'' (#24582)`` +================================================================================================= =========== ============================================================================= + +3.0.0 +..... + +Latest change: 2022-06-09 + +================================================================================================= =========== ======================================================================================================================= +Commit Committed Subject +================================================================================================= =========== ======================================================================================================================= +`dcdcf3a2b8 `_ 2022-06-09 ``Update release notes for RC2 release of Providers for May 2022 (#24307)`` +`717a7588bc `_ 2022-06-07 ``Update package description to remove double min-airflow specification (#24292)`` +`aeabe994b3 `_ 2022-06-07 ``Prepare docs for May 2022 provider's release (#24231)`` +`027b707d21 `_ 2022-06-05 ``Add explanatory note for contributors about updating Changelog (#24229)`` +`ddf9013098 `_ 2022-06-05 ``AIP-47 - Migrate databricks DAGs to new design #22442 (#24203)`` +`acf89510cd `_ 2022-06-04 ``fix: DatabricksSubmitRunOperator and DatabricksRunNowOperator cannot define .json as template_ext (#23622) (#23641)`` +`92ddcf4ac6 `_ 2022-05-27 ``Introduce 'flake8-implicit-str-concat' plugin to static checks (#23873)`` +`6150d28323 `_ 2022-05-22 ``Add Deferrable Databricks operators (#19736)`` +`cf5a78e91c `_ 2022-05-22 ``Fix UnboundLocalError when sql is empty list in DatabricksSqlHook (#23815)`` +`d0a5b3a4f2 `_ 2022-05-13 ``Add git_source to DatabricksSubmitRunOperator (#23620)`` +================================================================================================= =========== ======================================================================================================================= + +2.7.0 +..... + +Latest change: 2022-05-12 + +================================================================================================= =========== =========================================================================== +Commit Committed Subject +================================================================================================= =========== =========================================================================== +`75c60923e0 `_ 2022-05-12 ``Prepare provider documentation 2022.05.11 (#23631)`` +`428a439953 `_ 2022-05-09 ``Clean up in-line f-string concatenation (#23591)`` +`a58506b2a6 `_ 2022-04-26 ``Address review comments`` +`6a3d6cc32b `_ 2022-04-26 ``Update to the released version of DBSQL connector`` +`7b3bf4e435 `_ 2022-04-26 ``DatabricksSqlOperator - switch to databricks-sql-connector 2.x`` +`f02b0b6b40 `_ 2022-04-25 ``Further improvement of Databricks Jobs operators (#23199)`` +`8b6b0848a3 `_ 2022-04-23 ``Use new Breese for building, pulling and verifying the images. (#23104)`` +================================================================================================= =========== =========================================================================== + +2.6.0 +..... + +Latest change: 2022-04-13 + +================================================================================================= =========== =============================================================================== +Commit Committed Subject +================================================================================================= =========== =============================================================================== +`40831144be `_ 2022-04-13 ``Prepare for RC2 release of March Databricks provider (#22979)`` +`7be57eb256 `_ 2022-04-10 ``Databricks SQL operators are now Python 3.10 compatible (#22886)`` +`aa8c08db38 `_ 2022-04-10 ``Databricks: Correctly handle HTTP exception (#22885)`` +`6933022e94 `_ 2022-04-10 ``Fix new MyPy errors in main (#22884)`` +`56ab82ed7a `_ 2022-04-07 ``Prepare mid-April provider documentation. (#22819)`` +`1b12c93ed3 `_ 2022-03-31 ``Refactor 'DatabricksJobRunLink' to not create ad hoc TaskInstances (#22571)`` +`95169d1d07 `_ 2022-03-27 ``Add a link to Databricks Job Run (#22541)`` +`352d7f72dd `_ 2022-03-27 ``More operators for Databricks Repos (#22422)`` +`c063fc688c `_ 2022-03-25 ``Update black precommit (#22521)`` +================================================================================================= =========== =============================================================================== + +2.5.0 +..... + +Latest change: 2022-03-22 + +================================================================================================= =========== ============================================================== +Commit Committed Subject +================================================================================================= =========== ============================================================== +`d7dbfb7e26 `_ 2022-03-22 ``Add documentation for bugfix release of Providers (#22383)`` +`cc920963a6 `_ 2022-03-15 ``Operator for updating Databricks Repos (#22278)`` +================================================================================================= =========== ============================================================== + +2.4.0 +..... + +Latest change: 2022-03-14 + +================================================================================================= =========== ======================================================================= +Commit Committed Subject +================================================================================================= =========== ======================================================================= +`16adc035b1 `_ 2022-03-14 ``Add documentation for Classifier release for March 2022 (#22226)`` +`12e9e2c695 `_ 2022-03-14 ``Databricks hook - retry on HTTP Status 429 as well (#21852)`` +`af9d85ccd8 `_ 2022-03-13 ``Skip some tests for Databricks from running on Python 3.10 (#22221)`` +`4014194320 `_ 2022-03-08 ``Add new options to DatabricksCopyIntoOperator (#22076)`` +================================================================================================= =========== ======================================================================= + +2.3.0 +..... + +Latest change: 2022-03-07 + +================================================================================================= =========== ============================================================================= +Commit Committed Subject +================================================================================================= =========== ============================================================================= +`f5b96315fe `_ 2022-03-07 ``Add documentation for Feb Providers release (#22056)`` +`62bf1276f6 `_ 2022-03-01 ``Add-showing-runtime-error-feature-to-DatabricksSubmitRunOperator (#21709)`` +`27d19e7626 `_ 2022-02-27 ``Databricks SQL operators (#21363)`` +`a1845c68f9 `_ 2022-02-26 ``Databricks: add support for triggering jobs by name (#21663)`` +`7cca82495b `_ 2022-02-15 ``Updated Databricks docs for correct jobs 2.1 API and links (#21494)`` +`0a2d0d1ecb `_ 2022-02-12 ``Added template_ext = ('.json') to databricks operators #18925 (#21530)`` +`d94fa37830 `_ 2022-02-08 ``Fixed changelog for January 2022 (delayed) provider's release (#21439)`` +`6c3a67d4fc `_ 2022-02-05 ``Add documentation for January 2021 providers release (#21257)`` +`602abe8394 `_ 2022-01-20 ``Remove ':type' lines now sphinx-autoapi supports typehints (#20951)`` +================================================================================================= =========== ============================================================================= + +2.2.0 +..... + +Latest change: 2021-12-31 + +================================================================================================= =========== ================================================================================== +Commit Committed Subject +================================================================================================= =========== ================================================================================== +`f77417eb0d `_ 2021-12-31 ``Fix K8S changelog to be PyPI-compatible (#20614)`` +`97496ba2b4 `_ 2021-12-31 ``Update documentation for provider December 2021 release (#20523)`` +`0bf424f37f `_ 2021-12-30 ``Fix mypy databricks operator (#20598)`` +`d56e7b56bb `_ 2021-12-30 ``Fix template_fields type to have MyPy friendly Sequence type (#20571)`` +`a0821235fb `_ 2021-12-30 ``Use typed Context EVERYWHERE (#20565)`` +`c5c18c54fa `_ 2021-12-29 ``Databricks: fix verification of Managed Identity (#20550)`` +`d3b3161f0d `_ 2021-12-28 ``Remove 'host' as an instance attr in 'DatabricksHook' (#20540)`` +`58afc19377 `_ 2021-12-28 ``Add 'wait_for_termination' argument for Databricks Operators (#20536)`` +`e7659d08b0 `_ 2021-12-27 ``Update connection object to ''cached_property'' in ''DatabricksHook'' (#20526)`` +`cad39274d9 `_ 2021-12-14 ``Fix MyPy Errors for Databricks provider. (#20265)`` +================================================================================================= =========== ================================================================================== + +2.1.0 +..... + +Latest change: 2021-12-10 + +================================================================================================= =========== ================================================================================= +Commit Committed Subject +================================================================================================= =========== ================================================================================= +`820bfed515 `_ 2021-12-10 ``Prepare docs for provider's RC2 release (#20205)`` +`66f94f95c2 `_ 2021-12-10 ``Remove db call from 'DatabricksHook.__init__()' (#20180)`` +`545ca59ba9 `_ 2021-12-08 ``Unhide changelog entry for databricks (#20128)`` +`637db1a0ba `_ 2021-12-07 ``Update documentation for RC2 release of November Databricks Provider (#20086)`` +`728e94a47e `_ 2021-12-05 ``Refactor DatabricksHook (#19835)`` +`4925b37b66 `_ 2021-12-04 ``Databricks hook: fix expiration time check (#20036)`` +`853576d901 `_ 2021-11-30 ``Update documentation for November 2021 provider's release (#19882)`` +`11998848a4 `_ 2021-11-24 ``Databricks: add more methods to represent run state information (#19723)`` +`56bdfe7a84 `_ 2021-11-22 ``Databricks - allow Azure SP authentication on other Azure clouds (#19722)`` +`244627e3da `_ 2021-11-14 ``Databricks: allow to specify PAT in Password field (#19585)`` +`0a4a8bdb94 `_ 2021-11-14 ``Databricks jobs 2.1 (#19544)`` +`8ae878953b `_ 2021-11-09 ``Update Databricks API from 2.0 to 2.1 (#19412)`` +`28b51fb7bd `_ 2021-11-08 ``Authentication with AAD tokens in Databricks provider (#19335)`` +`3a0c455855 `_ 2021-11-07 ``Update Databricks operators to match latest version of API 2.0 (#19443)`` +`d9567eb106 `_ 2021-10-29 ``Prepare documentation for October Provider's release (#19321)`` +`f5ad26dcdd `_ 2021-10-21 ``Fixup string concatenations (#19099)`` +================================================================================================= =========== ================================================================================= + +2.0.2 +..... + +Latest change: 2021-09-30 + +================================================================================================= =========== ====================================================================================== +Commit Committed Subject +================================================================================================= =========== ====================================================================================== +`840ea3efb9 `_ 2021-09-30 ``Update documentation for September providers release (#18613)`` +`ef037e7021 `_ 2021-09-29 ``Static start_date and default arg cleanup for misc. provider example DAGs (#18597)`` +`0b7b13372f `_ 2021-09-18 ``Move DB call out of ''DatabricksHook.__init__'' (#18339)`` +================================================================================================= =========== ====================================================================================== + +2.0.1 +..... + +Latest change: 2021-08-30 + +================================================================================================= =========== ============================================================================ +Commit Committed Subject +================================================================================================= =========== ============================================================================ +`0a68588479 `_ 2021-08-30 ``Add August 2021 Provider's documentation (#17890)`` +`be75dcd39c `_ 2021-08-23 ``Update description about the new ''connection-types'' provider meta-data`` +`76ed2a49c6 `_ 2021-08-19 ``Import Hooks lazily individually in providers manager (#17682)`` +`87f408b1e7 `_ 2021-07-26 ``Prepares docs for Rc2 release of July providers (#17116)`` +`b916b75079 `_ 2021-07-15 ``Prepare documentation for July release of providers. (#17015)`` +`866a601b76 `_ 2021-06-28 ``Removes pylint from our toolchain (#16682)`` +================================================================================================= =========== ============================================================================ + +2.0.0 +..... + +Latest change: 2021-06-18 + +================================================================================================= =========== ================================================================= +Commit Committed Subject +================================================================================================= =========== ================================================================= +`bbc627a3da `_ 2021-06-18 ``Prepares documentation for rc2 release of Providers (#16501)`` +`cbf8001d76 `_ 2021-06-16 ``Synchronizes updated changelog after buggfix release (#16464)`` +`1fba5402bb `_ 2021-06-15 ``More documentation update for June providers release (#16405)`` +`9c94b72d44 `_ 2021-06-07 ``Updated documentation for June 2021 provider release (#16294)`` +`37681bca00 `_ 2021-05-07 ``Auto-apply apply_default decorator (#15667)`` +`807ad32ce5 `_ 2021-05-01 ``Prepares provider release after PIP 21 compatibility (#15576)`` +`df143aee8d `_ 2021-04-29 ``An initial rework of the "Concepts" docs (#15444)`` +`49cae1f052 `_ 2021-04-17 ``Add documentation for Databricks connection (#15410)`` +`68e4c4dcb0 `_ 2021-03-20 ``Remove Backport Providers (#14886)`` +================================================================================================= =========== ================================================================= + +1.0.1 +..... + +Latest change: 2021-02-04 + +================================================================================================= =========== ======================================================== +Commit Committed Subject +================================================================================================= =========== ======================================================== +`88bdcfa0df `_ 2021-02-04 ``Prepare to release a new wave of providers. (#14013)`` +`ac2f72c98d `_ 2021-02-01 ``Implement provider versioning tools (#13767)`` +`a9ac2b040b `_ 2021-01-23 ``Switch to f-strings using flynt. (#13732)`` +`3fd5ef3555 `_ 2021-01-21 ``Add missing logos for integrations (#13717)`` +`295d66f914 `_ 2020-12-30 ``Fix Grammar in PIP warning (#13380)`` +`6cf76d7ac0 `_ 2020-12-18 ``Fix typo in pip upgrade command :( (#13148)`` +================================================================================================= =========== ======================================================== + +1.0.0 +..... + +Latest change: 2020-12-09 + +================================================================================================= =========== ====================================================================================================================================================================== +Commit Committed Subject +================================================================================================= =========== ====================================================================================================================================================================== +`32971a1a2d `_ 2020-12-09 ``Updates providers versions to 1.0.0 (#12955)`` +`b40dffa085 `_ 2020-12-08 ``Rename remaing modules to match AIP-21 (#12917)`` +`9b39f24780 `_ 2020-12-08 ``Add support for dynamic connection form fields per provider (#12558)`` +`bd90136aaf `_ 2020-11-30 ``Move operator guides to provider documentation packages (#12681)`` +`c34ef853c8 `_ 2020-11-20 ``Separate out documentation building per provider (#12444)`` +`0080354502 `_ 2020-11-18 ``Update provider READMEs for 1.0.0b2 batch release (#12449)`` +`7ca0b6f121 `_ 2020-11-18 ``Enable Markdownlint rule MD003/heading-style/header-style (#12427) (#12438)`` +`ae7cb4a1e2 `_ 2020-11-17 ``Update wrong commit hash in backport provider changes (#12390)`` +`6889a333cf `_ 2020-11-15 ``Improvements for operators and hooks ref docs (#12366)`` +`7825e8f590 `_ 2020-11-13 ``Docs installation improvements (#12304)`` +`b027223132 `_ 2020-11-13 ``Add install/uninstall api to databricks hook (#12316)`` +`85a18e13d9 `_ 2020-11-09 ``Point at pypi project pages for cross-dependency of provider packages (#12212)`` +`59eb5de78c `_ 2020-11-09 ``Update provider READMEs for up-coming 1.0.0beta1 releases (#12206)`` +`b2a28d1590 `_ 2020-11-09 ``Moves provider packages scripts to dev (#12082)`` +`7e0d08e1f0 `_ 2020-11-09 ``Add how-to Guide for Databricks operators (#12175)`` +`4e8f9cc8d0 `_ 2020-11-03 ``Enable Black - Python Auto Formmatter (#9550)`` +`8c42cf1b00 `_ 2020-11-03 ``Use PyUpgrade to use Python 3.6 features (#11447)`` +`5a439e84eb `_ 2020-10-26 ``Prepare providers release 0.0.2a1 (#11855)`` +`872b1566a1 `_ 2020-10-25 ``Generated backport providers readmes/setup for 2020.10.29 (#11826)`` +`349b0811c3 `_ 2020-10-20 ``Add D200 pydocstyle check (#11688)`` +`16e7129719 `_ 2020-10-13 ``Added support for provider packages for Airflow 2.0 (#11487)`` +`0a0e1af800 `_ 2020-10-03 ``Fix Broken Markdown links in Providers README TOC (#11249)`` +`ca4238eb4d `_ 2020-10-02 ``Fixed month in backport packages to October (#11242)`` +`5220e4c384 `_ 2020-10-02 ``Prepare Backport release 2020.09.07 (#11238)`` +`54353f8745 `_ 2020-09-27 ``Increase type coverage for five different providers (#11170)`` +`966a06d96b `_ 2020-09-18 ``Fetching databricks host from connection if not supplied in extras. (#10762)`` +`9549274d11 `_ 2020-09-09 ``Upgrade black to 20.8b1 (#10818)`` +`fdd9b6f65b `_ 2020-08-25 ``Enable Black on Providers Packages (#10543)`` +`bfefcce0c9 `_ 2020-08-25 ``Updated REST API call so GET requests pass payload in query string instead of request body (#10462)`` +`3696c34c28 `_ 2020-08-24 ``Fix typo in the word "release" (#10528)`` +`2f2d8dbfaf `_ 2020-08-25 ``Remove all "noinspection" comments native to IntelliJ (#10525)`` +`ee7ca128a1 `_ 2020-08-22 ``Fix broken Markdown refernces in Providers README (#10483)`` +`cdec301254 `_ 2020-08-07 ``Add correct signature to all operators and sensors (#10205)`` +`7d24b088cd `_ 2020-07-25 ``Stop using start_date in default_args in example_dags (2) (#9985)`` +`e13a14c873 `_ 2020-06-21 ``Enable & Fix Whitespace related PyDocStyle Checks (#9458)`` +`d0e7db4024 `_ 2020-06-19 ``Fixed release number for fresh release (#9408)`` +`12af6a0800 `_ 2020-06-19 ``Final cleanup for 2020.6.23rc1 release preparation (#9404)`` +`c7e5bce57f `_ 2020-06-19 ``Prepare backport release candidate for 2020.6.23rc1 (#9370)`` +`f6bd817a3a `_ 2020-06-16 ``Introduce 'transfers' packages (#9320)`` +`0b0e4f7a4c `_ 2020-05-26 ``Preparing for RC3 relase of backports (#9026)`` +`00642a46d0 `_ 2020-05-26 ``Fixed name of 20 remaining wrongly named operators. (#8994)`` +`f1073381ed `_ 2020-05-22 ``Add support for spark python and submit tasks in Databricks operator(#8846)`` +`375d1ca229 `_ 2020-05-19 ``Release candidate 2 for backport packages 2020.05.20 (#8898)`` +`12c5e5d8ae `_ 2020-05-17 ``Prepare release candidate for backport packages (#8891)`` +`f3521fb0e3 `_ 2020-05-16 ``Regenerate readme files for backport package release (#8886)`` +`92585ca4cb `_ 2020-05-15 ``Added automated release notes generation for backport operators (#8807)`` +`649935e8ce `_ 2020-04-27 ``[AIRFLOW-8472]: 'PATCH' for Databricks hook '_do_api_call' (#8473)`` +`16903ba3a6 `_ 2020-04-24 ``[AIRFLOW-8474]: Adding possibility to get job_id from Databricks run (#8475)`` +`5648dfbc30 `_ 2020-03-23 ``Add missing call to Super class in 'amazon', 'cloudant & 'databricks' providers (#7827)`` +`3320e432a1 `_ 2020-02-24 ``[AIRFLOW-6817] Lazy-load 'airflow.DAG' to keep user-facing API untouched (#7517)`` +`4d03e33c11 `_ 2020-02-22 ``[AIRFLOW-6817] remove imports from 'airflow/__init__.py', replaced implicit imports with explicit imports, added entry to 'UPDATING.MD' - squashed/rebased (#7456)`` +`97a429f9d0 `_ 2020-02-02 ``[AIRFLOW-6714] Remove magic comments about UTF-8 (#7338)`` +`83c037873f `_ 2020-01-30 ``[AIRFLOW-6674] Move example_dags in accordance with AIP-21 (#7287)`` +`c42a375e79 `_ 2020-01-27 ``[AIRFLOW-6644][AIP-21] Move service classes to providers package (#7265)`` +================================================================================================= =========== ====================================================================================================================================================================== diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/connections/databricks.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/connections/databricks.rst.txt new file mode 100644 index 00000000000..7045d4a3ae2 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/connections/databricks.rst.txt @@ -0,0 +1,110 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + + +.. _howto/connection:databricks: + +Databricks Connection +========================== + +The Databricks connection type enables the Databricks & Databricks SQL Integration. + +Authenticating to Databricks +---------------------------- + +There are several ways to connect to Databricks using Airflow. + +1. Use a `Personal Access Token (PAT) + `_ + i.e. add a token to the Airflow connection. This is the recommended method. +2. Use Databricks login credentials + i.e. add the username and password used to login to the Databricks account to the Airflow connection. + Note that username/password authentication is discouraged and not supported for + :class:`~airflow.providers.databricks.operators.databricks_sql.DatabricksSqlOperator`. +3. Using Azure Active Directory (AAD) token generated from Azure Service Principal's ID and secret + (only on Azure Databricks). Service principal could be defined as a + `user inside workspace `_, or `outside of workspace having Owner or Contributor permissions `_ +4. Using Azure Active Directory (AAD) token obtained for `Azure managed identity `_, + when Airflow runs on the VM with assigned managed identity (system-assigned or user-assigned) + +Default Connection IDs +---------------------- + +Hooks and operators related to Databricks use ``databricks_default`` by default. + +Configuring the Connection +-------------------------- + +Host (required) + Specify the Databricks workspace URL + +Login (optional) + * If authentication with *Databricks login credentials* is used then specify the ``username`` used to login to Databricks. + * If authentication with *Azure Service Principal* is used then specify the ID of the Azure Service Principal + * If authentication with *PAT* is used then either leave this field empty or use 'token' as login (both work, the only difference is that if login is empty then token will be sent in request header as Bearer token, if login is 'token' then it will be sent using Basic Auth which is allowed by Databricks API, this may be useful if you plan to reuse this connection with e.g. HttpOperator) + * If authentication with *Databricks Service Principal OAuth* is used then specify the ID of the Service Principal (Databricks on AWS) + +Password (optional) + * If authentication with *Databricks login credentials* is used then specify the ``password`` used to login to Databricks. + * If authentication with *Azure Service Principal* is used then specify the secret of the Azure Service Principal + * If authentication with *PAT* is used, then specify PAT (recommended) + * If authentication with *Databricks Service Principal OAuth* is used then specify the secret of the Service Principal (Databricks on AWS) + +Extra (optional) + Specify the extra parameter (as json dictionary) that can be used in the Databricks connection. + + Following parameter could be used if using the *PAT* authentication method: + + * ``token``: Specify PAT to use. Consider to switch to specification of PAT in the Password field as it's more secure. + + Following parameters are necessary if using authentication with OAuth token for AWS Databricks Service Principal: + + * ``service_principal_oauth``: required boolean flag. If specified as ``true``, use the Client ID and Client Secret as the Username and Password. See `Authentication using OAuth for service principals `_. + + Following parameters are necessary if using authentication with AAD token: + + * ``azure_tenant_id``: ID of the Azure Active Directory tenant + * ``azure_resource_id``: optional Resource ID of the Azure Databricks workspace (required if Service Principal isn't + a user inside workspace) + * ``azure_ad_endpoint``: optional host name of Azure AD endpoint if you're using special `Azure Cloud (GovCloud, China, Germany) `_. The value must contain a protocol. For example: ``https://login.microsoftonline.de``. + + Following parameters are necessary if using authentication with AAD token for Azure managed identity: + + * ``use_azure_managed_identity``: required boolean flag to specify if managed identity needs to be used instead of + service principal + * ``azure_resource_id``: optional Resource ID of the Azure Databricks workspace (required if managed identity isn't + a user inside workspace) + + Following parameters could be set when using + :class:`~airflow.providers.databricks.operators.databricks_sql.DatabricksSqlOperator`: + + * ``http_path``: optional HTTP path of Databricks SQL endpoint or Databricks cluster. See `documentation `_. + * ``session_configuration``: optional map containing Spark session configuration parameters. + * named internal arguments to the ``Connection`` object from ``databricks-sql-connector`` package. + + +When specifying the connection using an environment variable you should specify +it using URI syntax. + +Note that all components of the URI should be URL-encoded. + +For example: + +.. code-block:: bash + + export AIRFLOW_CONN_DATABRICKS_DEFAULT='databricks://@host-url?token=yourtoken' diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/index.rst.txt new file mode 100644 index 00000000000..56b308b35e1 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/index.rst.txt @@ -0,0 +1,136 @@ + + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +``apache-airflow-providers-databricks`` +============================================ + + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: Basics + + Home + Changelog + Security + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: Guides + + Connection types + Operators + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: References + + Python API <_api/airflow/providers/databricks/index> + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: System tests + + System Tests <_api/tests/system/providers/databricks/index> + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: Resources + + Example DAGs + PyPI Repository + Installing from sources + +.. THE REMAINDER OF THE FILE IS AUTOMATICALLY GENERATED. IT WILL BE OVERWRITTEN AT RELEASE TIME! + + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: Commits + + Detailed list of commits + + +apache-airflow-providers-databricks package +------------------------------------------------------ + +`Databricks `__ + + +Release: 6.3.0 + +Provider package +---------------- + +This package is for the ``databricks`` provider. +All classes for this package are included in the ``airflow.providers.databricks`` python package. + +Installation +------------ + +You can install this package on top of an existing Airflow 2 installation via +``pip install apache-airflow-providers-databricks``. +For the minimum Airflow version supported, see ``Requirements`` below. + +Requirements +------------ + +The minimum Apache Airflow version supported by this provider package is ``2.6.0``. + +======================================= ========================== +PIP package Version required +======================================= ========================== +``apache-airflow`` ``>=2.6.0`` +``apache-airflow-providers-common-sql`` ``>=1.10.0`` +``requests`` ``>=2.27.0,<3`` +``databricks-sql-connector`` ``>=2.0.0,!=2.9.0,<3.0.0`` +``aiohttp`` ``>=3.9.2,<4`` +======================================= ========================== + +Cross provider package dependencies +----------------------------------- + +Those are dependencies that might be needed in order to use all the features of the package. +You need to install the specified provider packages in order to use them. + +You can install such cross-provider dependencies when installing from PyPI. For example: + +.. code-block:: bash + + pip install apache-airflow-providers-databricks[common.sql] + + +============================================================================================================ ============== +Dependent package Extra +============================================================================================================ ============== +`apache-airflow-providers-common-sql `_ ``common.sql`` +============================================================================================================ ============== + +Downloading official packages +----------------------------- + +You can download officially released packages and verify their checksums and signatures from the +`Official Apache Download site `_ + +* `The apache-airflow-providers-databricks 6.3.0 sdist package `_ (`asc `__, `sha512 `__) +* `The apache-airflow-providers-databricks 6.3.0 wheel package `_ (`asc `__, `sha512 `__) diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/installing-providers-from-sources.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/installing-providers-from-sources.rst.txt new file mode 100644 index 00000000000..b4e730f4ff2 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/installing-providers-from-sources.rst.txt @@ -0,0 +1,18 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +.. include:: ../exts/includes/installing-providers-from-sources.rst diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/copy_into.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/copy_into.rst.txt new file mode 100644 index 00000000000..71a3fa9e89a --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/copy_into.rst.txt @@ -0,0 +1,52 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +.. _howto/operator:DatabricksSqlCopyIntoOperator: + + +DatabricksCopyIntoOperator +========================== + +Use the :class:`~airflow.providers.databricks.operators.databricks_sql.DatabricksCopyIntoOperator` to import +data into Databricks table using `COPY INTO `_ +command. + + +Using the Operator +------------------ + +Operator loads data from a specified location into a table using a configured endpoint. The only required parameters are: + +* ``table_name`` - string with the table name +* ``file_location`` - string with the URI of data to load +* ``file_format`` - string specifying the file format of data to load. Supported formats are ``CSV``, ``JSON``, ``AVRO``, ``ORC``, ``PARQUET``, ``TEXT``, ``BINARYFILE``. +* One of ``sql_endpoint_name`` (name of Databricks SQL endpoint to use) or ``http_path`` (HTTP path for Databricks SQL endpoint or Databricks cluster). + +Other parameters are optional and could be found in the class documentation. + +Examples +-------- + +Importing CSV data +^^^^^^^^^^^^^^^^^^ + +An example usage of the DatabricksCopyIntoOperator to import CSV data into a table is as follows: + +.. exampleinclude:: /../../tests/system/providers/databricks/example_databricks_sql.py + :language: python + :start-after: [START howto_operator_databricks_copy_into] + :end-before: [END howto_operator_databricks_copy_into] diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/index.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/index.rst.txt new file mode 100644 index 00000000000..8eaf86b887f --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/index.rst.txt @@ -0,0 +1,28 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + + +Databricks Operators +==================== + + +.. toctree:: + :maxdepth: 1 + :glob: + + * diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/jobs_create.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/jobs_create.rst.txt new file mode 100644 index 00000000000..779095e92cd --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/jobs_create.rst.txt @@ -0,0 +1,91 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + + +DatabricksCreateJobsOperator +============================ + +Use the :class:`~airflow.providers.databricks.operators.DatabricksCreateJobsOperator` to create +(or reset) a Databricks job. This operator relies on past XComs to remember the ``job_id`` that +was created so that repeated calls with this operator will update the existing job rather than +creating new ones. When paired with the DatabricksRunNowOperator all runs will fall under the same +job within the Databricks UI. + + +Using the Operator +------------------ + +There are three ways to instantiate this operator. In the first way, you can take the JSON payload that you typically use +to call the ``api/2.1/jobs/create`` endpoint and pass it directly to our ``DatabricksCreateJobsOperator`` through the +``json`` parameter. With this approach you get full control over the underlying payload to Jobs REST API, including +execution of Databricks jobs with multiple tasks, but it's harder to detect errors because of the lack of the type checking. + +The second way to accomplish the same thing is to use the named parameters of the ``DatabricksCreateJobsOperator`` directly. Note that there is exactly +one named parameter for each top level parameter in the ``api/2.1/jobs/create`` endpoint. + +The third way is to use both the json parameter **AND** the named parameters. They will be merged +together. If there are conflicts during the merge, the named parameters will take precedence and +override the top level ``json`` keys. + +Currently the named parameters that ``DatabricksCreateJobsOperator`` supports are: + - ``name`` + - ``tags`` + - ``tasks`` + - ``job_clusters`` + - ``email_notifications`` + - ``webhook_notifications`` + - ``timeout_seconds`` + - ``schedule`` + - ``max_concurrent_runs`` + - ``git_source`` + - ``access_control_list`` + + +Examples +-------- + +Specifying parameters as JSON +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +An example usage of the DatabricksCreateJobsOperator is as follows: + +.. exampleinclude:: /../../tests/system/providers/databricks/example_databricks.py + :language: python + :start-after: [START howto_operator_databricks_jobs_create_json] + :end-before: [END howto_operator_databricks_jobs_create_json] + +Using named parameters +^^^^^^^^^^^^^^^^^^^^^^ + +You can also use named parameters to initialize the operator and run the job. + +.. exampleinclude:: /../../tests/system/providers/databricks/example_databricks.py + :language: python + :start-after: [START howto_operator_databricks_jobs_create_named] + :end-before: [END howto_operator_databricks_jobs_create_named] + +Pairing with DatabricksRunNowOperator +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can use the ``job_id`` that is returned by the DatabricksCreateJobsOperator in the +return_value XCom as an argument to the DatabricksRunNowOperator to run the job. + +.. exampleinclude:: /../../tests/system/providers/databricks/example_databricks.py + :language: python + :start-after: [START howto_operator_databricks_run_now] + :end-before: [END howto_operator_databricks_run_now] diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/repos_create.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/repos_create.rst.txt new file mode 100644 index 00000000000..6611a51cd6c --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/repos_create.rst.txt @@ -0,0 +1,69 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + + +DatabricksReposCreateOperator +============================= + +Use the :class:`~airflow.providers.databricks.operators.DatabricksReposCreateOperator` to create (and optionally checkout) a +`Databricks Repos `_ +via `api/2.0/repos `_ API endpoint. + + +Using the Operator +^^^^^^^^^^^^^^^^^^ + +To use this operator you need to provide at least ``git_url`` parameter. + +.. list-table:: + :widths: 15 25 + :header-rows: 1 + + * - Parameter + - Input + * - git_url: str + - Required HTTPS URL of a Git repository + * - git_provider: str + - Optional name of Git provider. Must be provided if we can't guess its name from URL. See API documentation for actual list of supported Git providers. + * - branch: str + - Optional name of the existing Git branch to checkout. + * - tag: str + - Optional name of the existing Git tag to checkout. + * - repo_path: str + - Optional path to a Databricks Repos, like, ``/Repos//repo_name``. If not specified, it will be created in the user's directory. + * - ignore_existing_repo: bool + - Don't throw exception if repository with given path already exists. + * - databricks_conn_id: string + - the name of the Airflow connection to use. + * - databricks_retry_limit: integer + - amount of times retry if the Databricks backend is unreachable. + * - databricks_retry_delay: decimal + - number of seconds to wait between retries. + +Examples +-------- + +Create a Databricks Repo +^^^^^^^^^^^^^^^^^^^^^^^^ + +An example usage of the DatabricksReposCreateOperator is as follows: + +.. exampleinclude:: /../../tests/system/providers/databricks/example_databricks_repos.py + :language: python + :start-after: [START howto_operator_databricks_repo_create] + :end-before: [END howto_operator_databricks_repo_create] diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/repos_delete.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/repos_delete.rst.txt new file mode 100644 index 00000000000..74d4b62972a --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/repos_delete.rst.txt @@ -0,0 +1,61 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + + +DatabricksReposDeleteOperator +============================= + +Use the :class:`~airflow.providers.databricks.operators.DatabricksReposDeleteOperator` to delete an existing +`Databricks Repo `_ +via `api/2.0/repos/ `_ API endpoint. + + +Using the Operator +^^^^^^^^^^^^^^^^^^ + +To use this operator you need to provide either ``repo_path`` or ``repo_id``. + +.. list-table:: + :widths: 15 25 + :header-rows: 1 + + * - Parameter + - Input + * - repo_path: str + - Path to existing Databricks Repos, like, ``/Repos//repo_name`` (required if ``repo_id`` isn't provided). + * - repo_id: str + - ID of existing Databricks Repos (required if ``repo_path`` isn't provided). + * - databricks_conn_id: string + - the name of the Airflow connection to use. + * - databricks_retry_limit: integer + - amount of times retry if the Databricks backend is unreachable. + * - databricks_retry_delay: decimal + - number of seconds to wait between retries. + +Examples +-------- + +Deleting Databricks Repo by specifying path +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +An example usage of the DatabricksReposDeleteOperator is as follows: + +.. exampleinclude:: /../../tests/system/providers/databricks/example_databricks_repos.py + :language: python + :start-after: [START howto_operator_databricks_repo_delete] + :end-before: [END howto_operator_databricks_repo_delete] diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/repos_update.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/repos_update.rst.txt new file mode 100644 index 00000000000..56af4edabbc --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/repos_update.rst.txt @@ -0,0 +1,66 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + + +DatabricksReposUpdateOperator +============================= + +Use the :class:`~airflow.providers.databricks.operators.DatabricksReposUpdateOperator` to update code in an existing +`Databricks Repos `_ to a given Git branch or tag +via `api/2.0/repos/ `_ API endpoint. + + +Using the Operator +^^^^^^^^^^^^^^^^^^ + +Usually this operator is used to update a source code of the Databricks job before its execution. +To use this operator you need to provide either ``branch`` or ``tag`` and either ``repo_path`` or ``repo_id``. + +.. list-table:: + :widths: 15 25 + :header-rows: 1 + + * - Parameter + - Input + * - branch: str + - Name of the existing Git branch to update to (required if ``tag`` isn't provided). + * - tag: str + - Name of the existing Git tag to update to (required if ``branch`` isn't provided). + * - repo_path: str + - Path to existing Databricks Repos, like, ``/Repos//repo_name`` (required if ``repo_id`` isn't provided). + * - repo_id: str + - ID of existing Databricks Repos (required if ``repo_path`` isn't provided). + * - databricks_conn_id: string + - the name of the Airflow connection to use. + * - databricks_retry_limit: integer + - amount of times retry if the Databricks backend is unreachable. + * - databricks_retry_delay: decimal + - number of seconds to wait between retries. + +Examples +-------- + +Updating Databricks Repo by specifying path +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +An example usage of the DatabricksReposUpdateOperator is as follows: + +.. exampleinclude:: /../../tests/system/providers/databricks/example_databricks_repos.py + :language: python + :start-after: [START howto_operator_databricks_repo_update] + :end-before: [END howto_operator_databricks_repo_update] diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/run_now.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/run_now.rst.txt new file mode 100644 index 00000000000..facf47e7d6c --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/run_now.rst.txt @@ -0,0 +1,57 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + + +DatabricksRunNowOperator +======================== + +Use the :class:`~airflow.providers.databricks.operators.DatabricksRunNowOperator` to trigger a run of an existing Databricks job +via `api/2.1/jobs/run-now `_ API endpoint. + + +Using the Operator +^^^^^^^^^^^^^^^^^^ + +There are two ways to instantiate this operator. In the first way, you can take the JSON payload that you typically use +to call the ``api/2.1/jobs/run-now`` endpoint and pass it directly to our ``DatabricksRunNowOperator`` through the ``json`` parameter. + +Another way to accomplish the same thing is to use the named parameters of the ``DatabricksRunNowOperator`` directly. +Note that there is exactly one named parameter for each top level parameter in the ``jobs/run-now`` endpoint. + +The only required parameters are either: + +* ``job_id`` - to specify ID of the existing Databricks job +* ``job_name`` - Name of the existing Databricks job. It will throw exception if job isn't found, of if there are multiple jobs with the same name. + +All other parameters are optional and described in documentation for ``DatabricksRunNowOperator``. For example, you can pass additional parameters to a job using one of the following parameters, depending on the type of tasks in the job: + +* ``notebook_params`` +* ``python_params`` +* ``python_named_parameters`` +* ``jar_params`` +* ``spark_submit_params`` +* ``idempotency_token`` +* ``repair_run`` +* ``cancel_previous_runs`` + +DatabricksRunNowDeferrableOperator +================================== + +Deferrable version of the :class:`~airflow.providers.databricks.operators.DatabricksRunNowOperator` operator. + +It allows to utilize Airflow workers more effectively using `new functionality introduced in Airflow 2.2.0 `_ diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/sql.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/sql.rst.txt new file mode 100644 index 00000000000..55bbf647585 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/sql.rst.txt @@ -0,0 +1,169 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +.. _howto/operator:DatabricksSqlOperator: + + +DatabricksSqlOperator +===================== + +Use the :class:`~airflow.providers.databricks.operators.databricks_sql.DatabricksSqlOperator` to execute SQL +on a `Databricks SQL warehouse `_ or a +`Databricks cluster `_. + + +Using the Operator +------------------ + +Operator executes given SQL queries against configured warehouse. The only required parameters are: + +* ``sql`` - SQL queries to execute. There are 3 ways of specifying SQL queries: + + 1. Simple string with SQL statement. + 2. List of strings representing SQL statements. + 3. Name of the file with SQL queries. File must have ``.sql`` extension. Each query should finish with ``;`` + +* One of ``sql_warehouse_name`` (name of Databricks SQL warehouse to use) or ``http_path`` (HTTP path for Databricks SQL warehouse or Databricks cluster). + +Other parameters are optional and could be found in the class documentation. + +Examples +-------- + +Selecting data +^^^^^^^^^^^^^^ + +An example usage of the DatabricksSqlOperator to select data from a table is as follows: + +.. exampleinclude:: /../../tests/system/providers/databricks/example_databricks_sql.py + :language: python + :start-after: [START howto_operator_databricks_sql_select] + :end-before: [END howto_operator_databricks_sql_select] + +Selecting data into a file +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +An example usage of the DatabricksSqlOperator to select data from a table and store in a file is as follows: + +.. exampleinclude:: /../../tests/system/providers/databricks/example_databricks_sql.py + :language: python + :start-after: [START howto_operator_databricks_sql_select_file] + :end-before: [END howto_operator_databricks_sql_select_file] + +Executing multiple statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +An example usage of the DatabricksSqlOperator to perform multiple SQL statements is as follows: + +.. exampleinclude:: /../../tests/system/providers/databricks/example_databricks_sql.py + :language: python + :start-after: [START howto_operator_databricks_sql_multiple] + :end-before: [END howto_operator_databricks_sql_multiple] + + +Executing multiple statements from a file +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +An example usage of the DatabricksSqlOperator to perform statements from a file is as follows: + +.. exampleinclude:: /../../tests/system/providers/databricks/example_databricks_sql.py + :language: python + :start-after: [START howto_operator_databricks_sql_multiple_file] + :end-before: [END howto_operator_databricks_sql_multiple_file] + + +DatabricksSqlSensor +=================== + +Use the :class:`~airflow.providers.databricks.sensors.sql.DatabricksSqlSensor` to run the sensor +for a table accessible via a Databricks SQL warehouse or interactive cluster. + +Using the Sensor +---------------- + +The sensor executes the SQL statement supplied by the user. The only required parameters are: + +* ``sql`` - SQL query to execute for the sensor. + +* One of ``sql_warehouse_name`` (name of Databricks SQL warehouse to use) or ``http_path`` (HTTP path for Databricks SQL warehouse or Databricks cluster). + +Other parameters are optional and could be found in the class documentation. + +Examples +-------- +Configuring Databricks connection to be used with the Sensor. + +.. exampleinclude:: /../../tests/system/providers/databricks/example_databricks_sensors.py + :language: python + :dedent: 4 + :start-after: [START howto_sensor_databricks_connection_setup] + :end-before: [END howto_sensor_databricks_connection_setup] + +Poking the specific table with the SQL statement: + +.. exampleinclude:: /../../tests/system/providers/databricks/example_databricks_sensors.py + :language: python + :dedent: 4 + :start-after: [START howto_sensor_databricks_sql] + :end-before: [END howto_sensor_databricks_sql] + + +DatabricksPartitionSensor +========================= + +Sensors are a special type of Operator that are designed to do exactly one thing - wait for something to occur. It can be time-based, or waiting for a file, or an external event, but all they do is wait until something happens, and then succeed so their downstream tasks can run. + +For the Databricks Partition Sensor, we check if a partition and its related value exists and if not, it waits until the partition value arrives. The waiting time and interval to check can be configured in the timeout and poke_interval parameters respectively. + +Use the :class:`~airflow.providers.databricks.sensors.partition.DatabricksPartitionSensor` to run the sensor +for a table accessible via a Databricks SQL warehouse or interactive cluster. + +Using the Sensor +---------------- + +The sensor accepts the table name and partition name(s), value(s) from the user and generates the SQL query to check if +the specified partition name, value(s) exist in the specified table. + +The required parameters are: + +* ``table_name`` (name of the table for partition check). + +* ``partitions`` (name of the partitions to check). + +* ``partition_operator`` (comparison operator for partitions, to be used for range or limit of values, such as partition_name >= partition_value). `Databricks comparison operators `_ are supported. + +* One of ``sql_warehouse_name`` (name of Databricks SQL warehouse to use) or ``http_path`` (HTTP path for Databricks SQL warehouse or Databricks cluster). + +Other parameters are optional and can be found in the class documentation. + +Examples +-------- +Configuring Databricks connection to be used with the Sensor. + +.. exampleinclude:: /../../tests/system/providers/databricks/example_databricks_sensors.py + :language: python + :dedent: 4 + :start-after: [START howto_sensor_databricks_connection_setup] + :end-before: [END howto_sensor_databricks_connection_setup] + +Poking the specific table for existence of data/partition: + +.. exampleinclude:: /../../tests/system/providers/databricks/example_databricks_sensors.py + :language: python + :dedent: 4 + :start-after: [START howto_sensor_databricks_partition] + :end-before: [END howto_sensor_databricks_partition] diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/submit_run.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/submit_run.rst.txt new file mode 100644 index 00000000000..706920458c6 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/operators/submit_run.rst.txt @@ -0,0 +1,136 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + + +.. _howto/operator:DatabricksSubmitRunOperator: + + +DatabricksSubmitRunOperator +=========================== + +Use the :class:`~airflow.providers.databricks.operators.DatabricksSubmitRunOperator` to submit +a new Databricks job via Databricks `api/2.1/jobs/runs/submit `_ API endpoint. + + +Using the Operator +------------------ + +There are three ways to instantiate this operator. In the first way, you can take the JSON payload that you typically use +to call the ``api/2.1/jobs/runs/submit`` endpoint and pass it directly to our ``DatabricksSubmitRunOperator`` through the +``json`` parameter. With this approach you get full control over the underlying payload to Jobs REST API, including +execution of Databricks jobs with multiple tasks, but it's harder to detect errors because of the lack of the type checking. + +.. code-block:: python + + json = { + "new_cluster": {"spark_version": "2.1.0-db3-scala2.11", "num_workers": 2}, + "notebook_task": { + "notebook_path": "/Users/airflow@example.com/PrepareData", + }, + } + notebook_run = DatabricksSubmitRunOperator(task_id="notebook_run", json=json) + +The second way to accomplish the same thing is to use the named parameters of the ``DatabricksSubmitRunOperator`` directly. Note that there is exactly +one named parameter for each top level parameter in the ``runs/submit`` endpoint. When using named parameters you must to specify following: + +* Task specification - it should be one of: + + * ``spark_jar_task`` - main class and parameters for the JAR task + * ``notebook_task`` - notebook path and parameters for the task + * ``spark_python_task`` - python file path and parameters to run the python file with + * ``spark_submit_task`` - parameters needed to run a ``spark-submit`` command + * ``pipeline_task`` - parameters needed to run a Delta Live Tables pipeline + * ``dbt_task`` - parameters needed to run a dbt project + +* Cluster specification - it should be one of: + * ``new_cluster`` - specs for a new cluster on which this task will be run + * ``existing_cluster_id`` - ID for existing cluster on which to run this task + +* ``pipeline_task`` - may refer to either a ``pipeline_id`` or ``pipeline_name`` + +In the case where both the json parameter **AND** the named parameters +are provided, they will be merged together. If there are conflicts during the merge, +the named parameters will take precedence and override the top level ``json`` keys. + +Currently the named parameters that ``DatabricksSubmitRunOperator`` supports are + - ``spark_jar_task`` + - ``notebook_task`` + - ``spark_python_task`` + - ``spark_submit_task`` + - ``pipeline_task`` + - ``dbt_task`` + - ``git_source`` + - ``new_cluster`` + - ``existing_cluster_id`` + - ``libraries`` + - ``run_name`` + - ``timeout_seconds`` + +.. code-block:: python + + new_cluster = {"spark_version": "10.1.x-scala2.12", "num_workers": 2} + notebook_task = { + "notebook_path": "/Users/airflow@example.com/PrepareData", + } + notebook_run = DatabricksSubmitRunOperator( + task_id="notebook_run", new_cluster=new_cluster, notebook_task=notebook_task + ) + +Another way to do is use the param tasks to pass array of objects to instantiate this operator. Here the value of tasks param that is used to invoke ``api/2.1/jobs/runs/submit`` endpoint is passed through the ``tasks`` param in ``DatabricksSubmitRunOperator``. Instead of invoking single task, you can pass array of task and submit a one-time run. + +.. code-block:: python + + tasks = [ + { + "new_cluster": {"spark_version": "2.1.0-db3-scala2.11", "num_workers": 2}, + "notebook_task": {"notebook_path": "/Users/airflow@example.com/PrepareData"}, + } + ] + notebook_run = DatabricksSubmitRunOperator(task_id="notebook_run", tasks=tasks) + + + +Examples +-------- + +Specifying parameters as JSON +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +An example usage of the DatabricksSubmitRunOperator is as follows: + +.. exampleinclude:: /../../tests/system/providers/databricks/example_databricks.py + :language: python + :start-after: [START howto_operator_databricks_json] + :end-before: [END howto_operator_databricks_json] + +Using named parameters +^^^^^^^^^^^^^^^^^^^^^^ + +You can also use named parameters to initialize the operator and run the job. + +.. exampleinclude:: /../../tests/system/providers/databricks/example_databricks.py + :language: python + :start-after: [START howto_operator_databricks_named] + :end-before: [END howto_operator_databricks_named] + +DatabricksSubmitRunDeferrableOperator +===================================== + +Deferrable version of the :class:`~airflow.providers.databricks.operators.DatabricksSubmitRunOperator` operator. + +It allows to utilize Airflow workers more effectively using `new functionality introduced in Airflow 2.2.0 `_ diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/security.rst.txt b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/security.rst.txt new file mode 100644 index 00000000000..afa13dac6fc --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sources/security.rst.txt @@ -0,0 +1,18 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +.. include:: ../exts/includes/security.rst diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css new file mode 100644 index 00000000000..eb19f698afc --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css @@ -0,0 +1 @@ +.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative}details.sd-dropdown .sd-summary-title{font-weight:700;padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary{list-style:none;padding:1em}details.sd-dropdown summary .sd-octicon.no-title{vertical-align:middle}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown summary::-webkit-details-marker{display:none}details.sd-dropdown summary:focus{outline:none}details.sd-dropdown .sd-summary-icon{margin-right:.5em}details.sd-dropdown .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary:hover .sd-summary-up svg,details.sd-dropdown summary:hover .sd-summary-down svg{opacity:1;transform:scale(1.1)}details.sd-dropdown .sd-summary-up svg,details.sd-dropdown .sd-summary-down svg{display:block;opacity:.6}details.sd-dropdown .sd-summary-up,details.sd-dropdown .sd-summary-down{pointer-events:none;position:absolute;right:1em;top:1em}details.sd-dropdown[open]>.sd-summary-title .sd-summary-down{visibility:hidden}details.sd-dropdown:not([open])>.sd-summary-title .sd-summary-up{visibility:hidden}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #0071bc;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0060a0;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem} diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_sphinx_design_static/design-tabs.js b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sphinx_design_static/design-tabs.js new file mode 100644 index 00000000000..36b38cf0d91 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_sphinx_design_static/design-tabs.js @@ -0,0 +1,27 @@ +var sd_labels_by_text = {}; + +function ready() { + const li = document.getElementsByClassName("sd-tab-label"); + for (const label of li) { + syncId = label.getAttribute("data-sync-id"); + if (syncId) { + label.onclick = onLabelClick; + if (!sd_labels_by_text[syncId]) { + sd_labels_by_text[syncId] = []; + } + sd_labels_by_text[syncId].push(label); + } + } +} + +function onLabelClick() { + // Activate other inputs with the same sync id. + syncId = this.getAttribute("data-sync-id"); + for (label of sd_labels_by_text[syncId]) { + if (label === this) continue; + label.previousElementSibling.checked = true; + } + window.localStorage.setItem("sphinx-design-last-tab", syncId); +} + +document.addEventListener("DOMContentLoaded", ready, false); diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/_gen/css/main-custom.min.css b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/_gen/css/main-custom.min.css new file mode 100644 index 00000000000..46f1de59325 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/_gen/css/main-custom.min.css @@ -0,0 +1 @@ +@charset "UTF-8";@import "https://fonts.googleapis.com/css?family=Rubik:500&display=swap";@import "https://fonts.googleapis.com/css?family=Roboto:400,400i,500,700&display=swap";@import "https://fonts.googleapis.com/css?family=Roboto+Mono:400,700&display=swap";.header__large--cerulean-blue{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#017cee}.header__large--shamrock{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#00ad46}.header__large--bright-sky-blue{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#0cb6ff}.header__large--melon{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#ff7557}.header__large--vermillion{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#e43921}.header__large--aqua{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#11e1ee}.header__large--shamrock-green{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#04d659}.header__large--aqua-blue{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#00c7d4}.header__large--white{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#fff}.header__large--brownish-grey{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#707070}.header__large--very-light-pink{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#cbcbcb}.header__large--slate-grey{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#636365}.header__large--greyish-brown,#header-canvas .text-area--header{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#51504f}.header__medium--cerulean-blue{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#017cee}.header__medium--shamrock{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#00ad46}.header__medium--bright-sky-blue{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#0cb6ff}.header__medium--melon{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#ff7557}.header__medium--vermillion{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#e43921}.header__medium--aqua{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#11e1ee}.header__medium--shamrock-green{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#04d659}.header__medium--aqua-blue{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#00c7d4}.header__medium--white{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#fff}.header__medium--brownish-grey{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#707070}.header__medium--very-light-pink{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#cbcbcb}.header__medium--slate-grey{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#636365}.header__medium--greyish-brown,.page-header{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#51504f}.header__small--cerulean-blue{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#017cee}.header__small--shamrock{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#00ad46}.header__small--bright-sky-blue{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#0cb6ff}.header__small--melon{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#ff7557}.header__small--vermillion{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#e43921}.header__small--aqua{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#11e1ee}.header__small--shamrock-green{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#04d659}.header__small--aqua-blue{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#00c7d4}.header__small--white{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#fff}.header__small--brownish-grey{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#707070}.header__small--very-light-pink{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#cbcbcb}.header__small--slate-grey{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#636365}.header__small--greyish-brown,.blogpost-content__metadata--title,.community--header-join,.community--committers-header{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#51504f}.header__xsmall--cerulean-blue{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#017cee}.header__xsmall--shamrock{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#00ad46}.header__xsmall--bright-sky-blue{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#0cb6ff}.header__xsmall--melon{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#ff7557}.header__xsmall--vermillion{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#e43921}.header__xsmall--aqua{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#11e1ee}.header__xsmall--shamrock-green{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#04d659}.header__xsmall--aqua-blue{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#00c7d4}.header__xsmall--white{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#fff}.header__xsmall--brownish-grey{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#707070}.header__xsmall--very-light-pink{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#cbcbcb}.header__xsmall--slate-grey{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#636365}.header__xsmall--greyish-brown,.feature-item--header,.text-with-icon-item--header{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#51504f}.subtitle__large--cerulean-blue,.box-event__meetup--location{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#017cee}.subtitle__large--shamrock{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#00ad46}.subtitle__large--bright-sky-blue{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#0cb6ff}.subtitle__large--melon{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#ff7557}.subtitle__large--vermillion{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#e43921}.subtitle__large--aqua{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#11e1ee}.subtitle__large--shamrock-green{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#04d659}.subtitle__large--aqua-blue{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#00c7d4}.subtitle__large--white{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#fff}.subtitle__large--brownish-grey,.quote--text,.page-subtitle,.blogpost-content__metadata--description,#header-canvas .text-area--subheader{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#707070}.subtitle__large--very-light-pink{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#cbcbcb}.subtitle__large--slate-grey{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#636365}.subtitle__large--greyish-brown,.box-event__blogpost--header,.markdown-content h1,.markdown-content h2,.markdown-content h3,.markdown-content h4,.markdown-content h5{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#51504f}.subtitle__medium--cerulean-blue,ol.counter-blue li::before{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#017cee}.subtitle__medium--shamrock{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#00ad46}.subtitle__medium--bright-sky-blue{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#0cb6ff}.subtitle__medium--melon{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#ff7557}.subtitle__medium--vermillion{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#e43921}.subtitle__medium--aqua{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#11e1ee}.subtitle__medium--shamrock-green{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#04d659}.subtitle__medium--aqua-blue{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#00c7d4}.subtitle__medium--white{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#fff}.subtitle__medium--brownish-grey,.box-event__integration--name{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#707070}.subtitle__medium--very-light-pink{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#cbcbcb}.subtitle__medium--slate-grey{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#636365}.subtitle__medium--greyish-brown,.roadmap .td-sidebar nav>ul>li>a{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#51504f}.bodytext__medium--cerulean-blue,.box-event__blogpost--author,.box-event__meetup--next-meetup,.tag,.new-entry--link,.blogpost-content__metadata--author{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#017cee}.bodytext__medium--shamrock{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#00ad46}.bodytext__medium--bright-sky-blue{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#0cb6ff}.bodytext__medium--melon{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#ff7557}.bodytext__medium--vermillion{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#e43921}.bodytext__medium--aqua{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#11e1ee}.bodytext__medium--shamrock-green{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#04d659}.bodytext__medium--aqua-blue{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#00c7d4}.bodytext__medium--white,footer .footer-section span{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#fff}.bodytext__medium--brownish-grey,ol.counter-blue li,ul.ticks-blue li,.box-event__blogpost--description,.box-event__blogpost--date,.box-event__case-study--quote,.box-event__meetup--members,.markdown-content p,.markdown-content span,.feature-item--text,.text-with-icon-item--text,.video-list__item .video-list__item--title,.blogpost-content__metadata--date,.install--description,.roadmap .breadcrumb-item a,.roadmap .td-sidebar li>a,.sidebar__version-selector a{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#707070}.bodytext__medium--very-light-pink{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#cbcbcb}.bodytext__medium--slate-grey{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#636365}.bodytext__medium--greyish-brown,.box-event__committer--nick,.quote--author,.list-link,.install__accordions-content--header,.navbar__text-link{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#51504f}.bodytext__mobile--cerulean-blue{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#017cee}.bodytext__mobile--shamrock{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#00ad46}.bodytext__mobile--bright-sky-blue{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#0cb6ff}.bodytext__mobile--melon{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#ff7557}.bodytext__mobile--vermillion{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#e43921}.bodytext__mobile--aqua{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#11e1ee}.bodytext__mobile--shamrock-green{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#04d659}.bodytext__mobile--aqua-blue{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#00c7d4}.bodytext__mobile--white{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#fff}.bodytext__mobile--brownish-grey{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#707070}.bodytext__mobile--very-light-pink{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#cbcbcb}.bodytext__mobile--slate-grey{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#636365}.bodytext__mobile--greyish-brown{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#51504f}.bodytext__small--cerulean-blue{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#017cee}.bodytext__small--shamrock{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#00ad46}.bodytext__small--bright-sky-blue{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#0cb6ff}.bodytext__small--melon{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#ff7557}.bodytext__small--vermillion{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#e43921}.bodytext__small--aqua{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#11e1ee}.bodytext__small--shamrock-green{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#04d659}.bodytext__small--aqua-blue{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#00c7d4}.bodytext__small--white{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#fff}.bodytext__small--brownish-grey{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#707070}.bodytext__small--very-light-pink{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#cbcbcb}.bodytext__small--slate-grey{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#636365}.bodytext__small--greyish-brown{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#51504f}.bodytext__xsmall--cerulean-blue{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#017cee}.bodytext__xsmall--shamrock{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#00ad46}.bodytext__xsmall--bright-sky-blue{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#0cb6ff}.bodytext__xsmall--melon{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#ff7557}.bodytext__xsmall--vermillion{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#e43921}.bodytext__xsmall--aqua{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#11e1ee}.bodytext__xsmall--shamrock-green{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#04d659}.bodytext__xsmall--aqua-blue{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#00c7d4}.bodytext__xsmall--white{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#fff}.bodytext__xsmall--brownish-grey{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#707070}.bodytext__xsmall--very-light-pink{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#cbcbcb}.bodytext__xsmall--slate-grey{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#636365}.bodytext__xsmall--greyish-brown{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#51504f}.monotext--cerulean-blue{font-family:roboto mono,monospace;color:#017cee;font-size:14px;line-height:1.71}.monotext--shamrock{font-family:roboto mono,monospace;color:#00ad46;font-size:14px;line-height:1.71}.monotext--bright-sky-blue{font-family:roboto mono,monospace;color:#0cb6ff;font-size:14px;line-height:1.71}.monotext--melon{font-family:roboto mono,monospace;color:#ff7557;font-size:14px;line-height:1.71}.monotext--vermillion{font-family:roboto mono,monospace;color:#e43921;font-size:14px;line-height:1.71}.monotext--aqua{font-family:roboto mono,monospace;color:#11e1ee;font-size:14px;line-height:1.71}.monotext--shamrock-green{font-family:roboto mono,monospace;color:#04d659;font-size:14px;line-height:1.71}.monotext--aqua-blue{font-family:roboto mono,monospace;color:#00c7d4;font-size:14px;line-height:1.71}.monotext--white{font-family:roboto mono,monospace;color:#fff;font-size:14px;line-height:1.71}.monotext--brownish-grey,.markdown-content pre span,pre span{font-family:roboto mono,monospace;color:#707070;font-size:14px;line-height:1.71}.monotext--very-light-pink{font-family:roboto mono,monospace;color:#cbcbcb;font-size:14px;line-height:1.71}.monotext--slate-grey{font-family:roboto mono,monospace;color:#636365;font-size:14px;line-height:1.71}.monotext--greyish-brown{font-family:roboto mono,monospace;color:#51504f;font-size:14px;line-height:1.71}.font-weight-normal{font-weight:400!important}.font-weight-500{font-weight:500!important}.font-weight-bold{font-weight:700!important}details.accordion{padding:40px 30px;border-bottom:solid 1px #cbcbcb;-webkit-transition:ease 1s;-o-transition:ease 1s;transition:ease 1s}details.accordion:first-of-type{border-top:solid 1px #cbcbcb}details.accordion summary{position:relative;display:block;outline:none}details.accordion summary::-webkit-details-marker{display:none}details.accordion .accordion__summary-content{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;max-width:750px;margin-right:40px}details.accordion .accordion__summary-content--icon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;width:60px;margin-right:42px}details.accordion .accordion__summary-content--header{margin-bottom:20px}details.accordion .accordion__arrow{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;position:absolute;width:36px;height:36px;top:0;right:0;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;border:solid 1px #017cee;border-radius:50%}details.accordion .accordion__arrow svg{-webkit-transition:ease-out .2s;-o-transition:ease-out .2s;transition:ease-out .2s}details.accordion[open] .accordion__arrow svg{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}details.accordion .accordion__content{margin-top:30px;margin-right:36px}details.accordion .accordion__content.indented{margin-left:102px}@media(max-width:1280px){details.accordion{padding:30px 0}details.accordion .accordion__summary-content--icon{-webkit-box-align:unset;-webkit-align-items:unset;-ms-flex-align:unset;align-items:unset;margin-right:20px;margin-top:28px}details.accordion .accordion__arrow{width:28px;height:28px;top:5px}details.accordion .accordion__content.indented{margin-left:80px}details.accordion .accordion__content ol.counter-blue{margin-left:-38px!important}}button{cursor:pointer;border:1px solid;border-radius:5px;padding:9px 29px;-webkit-transition:all ease-out .2s;-o-transition:all ease-out .2s;transition:all ease-out .2s}button:disabled{cursor:not-allowed}button.btn-filled{border-color:#017cee;background-color:#017cee}button.btn-filled:hover{border-color:#0cb6ff;background-color:#0cb6ff}button.btn-with-icon{padding:14px 20px}button.btn-with-icon svg{height:30px;width:auto;padding-right:15px}button.btn-with-icon span{display:inline-block;line-height:30px;vertical-align:middle}button.btn-hollow{background-color:#fff}button.btn-hollow.btn-blue{color:#017cee;border-color:#017cee}button.btn-hollow.btn-blue:disabled{color:#cbcbcb;border-color:#cbcbcb}button.btn-hollow.btn-blue:hover:enabled{color:#fff;background-color:#017cee}button.btn-hollow.btn-brown{border-color:#cbcbcb}button.btn-hollow.btn-brown:hover{background-color:#51504f;border-color:#51504f}button.btn-hollow.btn-brown:hover span{color:#fff}button.btn-hollow.btn-brown:hover svg path{fill:#fff}button.with-box-shadow{-webkit-box-shadow:0 2px 6px 0 rgba(0,0,0,.12);box-shadow:0 2px 6px 0 rgba(0,0,0,.12)}@media(max-width:1280px){button{padding:4px 17px}}ol.counter-blue,ul.ticks-blue{list-style:none;margin-bottom:0}ol.counter-blue li,ul.ticks-blue li{position:relative;padding-left:10px}ol.counter-blue li::before,ul.ticks-blue li::before{position:absolute;border:solid 1px #017cee;border-radius:50%}ol.counter-blue{counter-reset:custom-counter;padding-left:-webkit-calc(26px + 2px);padding-left:calc(26px + 2px)}ol.counter-blue li{counter-increment:custom-counter;margin-bottom:25px}ol.counter-blue li::before{content:counter(custom-counter);-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;top:-2px;left:-webkit-calc(-1 * 26px);left:calc(-1 * 26px);width:26px;height:26px;text-align:center;line-height:26px}ul.ticks-blue{padding-left:-webkit-calc(24px + 2px);padding-left:calc(24px + 2px)}ul.ticks-blue li{margin-bottom:22px}ul.ticks-blue li::before{content:"";left:-webkit-calc(-1 * 24px);left:calc(-1 * 24px);width:24px;height:24px;background-position:50%;background-repeat:no-repeat;background-image:url(/images/tick.svg)}.list-items{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin:-20px;-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch}@media(max-width:1280px){.list-items{margin:auto;max-width:580px}}@media(max-width:640px){.list-items{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}}.list-item{width:25%;padding:20px}@media(min-width:1920px){.list-item{width:20%}}@media(max-width:1280px){.list-item{padding:10px;width:50%}}@media(max-width:640px){.list-item{width:100%}}.list-item--wide{width:50%}@media(max-width:1280px){.list-item--wide{width:100%}}.card{border:solid 1px #cbcbcb;border-radius:5px;padding:30px 10px;height:100%}.box-event{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.box-event__blogpost{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;padding:0 20px}.box-event__blogpost--metadata{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;margin-bottom:20px}.box-event__blogpost--header{margin-bottom:4px}.box-event__blogpost--author{font-weight:500}.box-event__blogpost--description{margin-bottom:20px}.box-event__case-study{padding:18px 18px 0;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.box-event__case-study--logo{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;height:60px;width:100%;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.box-event__case-study--logo svg,.box-event__case-study--logo img{max-height:100%;max-width:100%}.box-event__case-study--quote{font-style:italic;margin:30px 0 20px;text-align:center}.box-event__case-study--quote::before{content:"“"}.box-event__case-study--quote::after{content:"”"}.box-event__committer--nick{font-weight:500;margin-top:12px}.box-event__committer--social-media-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.box-event__committer--social-media-icon{margin:0 6px}.box-event__meetup--location{margin-bottom:10px;text-align:center}.box-event__meetup--members{margin-bottom:30px}.box-event__meetup--members span{vertical-align:middle}.box-event__meetup--next-meetup{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;min-height:52px;margin-bottom:20px;text-align:center}.box-event__integration{height:208px;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.box-event__integration--logo{margin:auto 0;-webkit-filter:grayscale(1);filter:grayscale(1);opacity:.6;max-width:100%;max-height:100%}.box-event__integration--name{font-weight:700;text-align:center}.box-event__integration:hover .box-event__integration--logo{-webkit-filter:none;filter:none;opacity:1}.box-event.hoverable-icon svg,.box-event.hoverable-icon img{-webkit-filter:grayscale(1);filter:grayscale(1);opacity:.6;-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s}.box-event.hoverable-icon:hover svg,.box-event.hoverable-icon:hover img{-webkit-filter:none;filter:none;opacity:1}@media(max-width:640px){.box-event__blogpost--metadata{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.box-event__blogpost--date{margin-top:17px}}.avatar{border-radius:50%;width:80px;height:80px}.quote{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;border-bottom:solid 1px #cbcbcb;padding:0 78px 60px}.quote--text{text-align:center;font-weight:400}.quote--text::before{content:"“"}.quote--text::after{content:"”"}.quote--author{text-align:center;font-weight:500;margin-bottom:32px}.quote--logo{max-height:140px;margin:0 auto}@media(max-width:640px){.quote{padding:0 0 40px}}.pager{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;margin-top:60px}.case-study-page{max-width:790px!important;margin:60px auto 0}@media(max-width:640px){.case-study-page{margin-top:40px}}.markdown-content h1,.markdown-content h2,.markdown-content h3,.markdown-content h4,.markdown-content h5{margin-top:40px;margin-bottom:20px}.markdown-content p,.markdown-content span{margin-bottom:30px;margin-top:20px}.markdown-content img{width:100%}.markdown-content table{border-collapse:collapse;width:100%}.markdown-content th{background:#ccc}.markdown-content th,.markdown-content td{border:1px solid #ccc;padding:8px}.markdown-content tr:nth-child(even){background:#efefef}.markdown-content tr:hover{background:#d1d1d1}.markdown-content li{color:#707070}.base-layout{padding:123px 0 40px}.base-layout--button{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;position:-webkit-sticky;position:sticky;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;margin-left:auto;margin-right:40px;bottom:40px;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;z-index:1}@media(max-width:1280px){.base-layout{padding:76px 0 60px}.base-layout--button{display:none}}.page-header{text-align:center;margin-bottom:16px}@media(max-width:1280px){.page-header{font-size:36px!important;line-height:1.22!important}}.page-subtitle{text-align:center;font-weight:400!important;margin-bottom:80px}@media(max-width:1280px){.page-subtitle{font-family:roboto,sans-serif!important;font-size:16px!important;line-height:1.63!important;margin-bottom:30px}}.container{margin-top:44px;max-width:1200px}@media(min-width:1920px){.container{max-width:1510px}}@media(max-width:1280px){.container>*{max-width:630px;margin-left:auto;margin-right:auto}.container .no-width-restriction{max-width:none}}@media(max-width:640px){.container>*{max-width:306px}}.container-fluid{padding-left:20px;padding-right:20px}.show-more-button{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;margin:60px auto 0}@media(max-width:1280px){.show-more-button{margin-top:30px}}@media(max-width:1280px){.desktop-only{display:none}}@media(min-width:calc(1280px + 1px)){.no-desktop{display:none}}@media(min-width:calc(640px + 1px)){.mobile-only{display:none}}.features-list{margin:76px auto 100px;max-width:720px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}@media(min-width:1920px){.features-list{max-width:unset;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;margin-top:0}}@media(max-width:640px){.features-list{margin-top:0}}.feature-item{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin:44px auto 0}.feature-item--icon-box{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;max-width:150px;width:100%;height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;margin-top:18px}.feature-item--text-box{margin-left:60px}@media(min-width:1920px),(max-width:1280px){.feature-item{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.feature-item--icon-box{margin-top:0;margin-bottom:20px;max-width:unset}.feature-item--text-box{margin-left:0;text-align:center}}@media(min-width:1920px){.feature-item{margin-top:60px;max-width:392px;margin-left:40px;margin-right:40px}}@media(max-width:1280px){.feature-item{margin-top:40px;max-width:260px}.feature-item svg{height:60px;width:auto}.feature-item--header{font-family:roboto,sans-serif!important;font-size:24px!important;line-height:1.5!important}.feature-item--text{font-size:14px!important;line-height:1.57!important}}.text-with-icon-list{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;max-width:940px;margin:0 auto 100px;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.text-with-icon-item{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-width:410px;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;margin-top:54px}.text-with-icon-item svg{height:100px}.text-with-icon-item--header{text-align:center;margin-top:23px}.text-with-icon-item--text{text-align:center}@media(min-width:1920px){.text-with-icon-list{max-width:unset}.text-with-icon-item{max-width:305px}}@media(max-width:1280px){.text-with-icon-item{margin-top:30px;max-width:276px}.text-with-icon-item svg{width:70px;height:70px}.text-with-icon-item--header{font-family:roboto,sans-serif;font-size:24px;line-height:1.5;margin-top:16px}.text-with-icon-item--text{font-size:14px;line-height:1.57}}@media(max-width:640px){.text-with-icon-list{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}}.video-section{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;border:solid 1px #cbcbcb;padding:40px}@media(max-width:1280px){.video-section{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-width:560px;margin:0 auto;padding:20px}}.video-wrapper{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.video-wrapper .video-container{display:none}.video-wrapper .video-container:last-child{display:block}.video-wrapper .anchor{position:fixed}.video-wrapper .anchor:target+.video-container{display:block}.video-wrapper .anchor:target+.video-container~.video-container{display:none}.video-list-wrapper{overflow-y:auto;max-height:403px;max-width:370px;width:100%;margin-left:40px}@media(max-width:1280px){.video-list-wrapper{max-width:unset;margin-left:0}}.video-list-wrapper::-webkit-scrollbar{-webkit-appearance:none}.video-list-wrapper::-webkit-scrollbar-thumb{border-radius:8px;border:2px solid #fff;background-color:rgba(0,0,0,.5)}.video-list-wrapper::-webkit-scrollbar:vertical{width:9px}.video-list{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end}.video-list__item{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;border-bottom:solid 1px #cbcbcb;padding:16px 0}.video-list__item .video-list__item--title{margin-left:9px;vertical-align:middle}.video-list__item--icon-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.video-list__item:hover .video-list__item--title,.video-list__item.active .video-list__item--title{font-weight:500}.video-list__item:hover svg path,.video-list__item.active svg path{fill:#707070;stroke:none}.tag{display:block;background-color:rgba(1,124,238,.25);padding:1px 15px;border-radius:5px;-webkit-transition:.2s;-o-transition:.2s;transition:.2s;margin:7px}.tag.active,.tag:hover{background-color:#017cee;color:#fff}.tags-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;margin:-7px}@media(max-width:640px){.tags-container{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;margin-bottom:7px}}.all-tags-container{margin:30px 0}.blog__list-items-wrapper{max-width:1200px;margin:30px auto 0}@media(max-width:1280px){.blog__list-items-wrapper{max-width:580px}}.new-entry{margin-bottom:20px}.new-entry--link{font-weight:500}@media(max-width:1280px){.new-entry{margin-bottom:10px;padding-left:10px}}.blogpost-content{max-width:790px;margin:0 auto}.blogpost-content--header-wrapper{border-bottom:solid 1px #cbcbcb}.blogpost-content__metadata--container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;margin-bottom:30px}.blogpost-content__metadata--title{margin-bottom:20px}.blogpost-content__metadata--author{font-weight:500;margin-bottom:30px;margin-right:17px}.blogpost-content__metadata--social-media-icon{margin-right:7px}.blogpost-content__metadata--description{font-weight:400;margin-bottom:30px}.blogpost-content__metadata--date{margin-top:17px}@media(max-width:640px){.blogpost-content__metadata--container{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;margin-bottom:19px}.blogpost-content__metadata--title{font-family:roboto,sans-serif!important;font-size:24px!important;line-height:1.5!important;max-width:272px;margin-bottom:13px}.blogpost-content__metadata--author{margin-bottom:20px}.blogpost-content__metadata--description{font-family:roboto,sans-serif!important;font-weight:400!important;font-size:16px!important;line-height:1.63!important;margin-bottom:20px}}.blog-pager{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;max-width:1200px;margin:60px auto 0}.blog-pager .pager{margin-top:40px;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.home-page-layout.base-layout{padding-top:70px}@media(max-width:640px){.home-page-layout.base-layout{padding-top:16px}}.principles-header{margin-top:20px;margin-bottom:4px}.integrations-header{margin-bottom:60px}@media(max-width:640px){.integrations-header{margin-bottom:30px}}#integrations .list-items{margin-top:40px}@media(max-width:640px){#integrations .list-items{margin-top:20px}}.video-section-container{margin:80px auto;max-width:1200px}@media(max-width:640px){.video-section-container{margin:60px 0}}.host-header{margin-bottom:6px}.meetups{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.meetups>.list-items{margin-top:40px;margin-bottom:40px;width:100%}@media(max-width:1280px){.meetups>.list-items{margin-top:30px;margin-bottom:30px}}@media(max-width:640px){.meetups>.list-items{margin-bottom:10px}}.meetups-page.page-subtitle{margin-bottom:0}.list-link{text-decoration:underline}.community--header-container{max-width:936px;margin:0 auto}.community--header-join{text-align:center}.community--accordion-container{margin:60px 18px}.community--committers-header{text-align:center;margin-top:70px;margin-bottom:40px}.community--committers-header.large-margin{margin-top:100px;margin-bottom:40px}@media(min-width:1920px){.community .list-items{max-width:1220px;margin-right:auto;margin-left:auto}.community .list-item{width:25%}}@media(max-width:1280px){.community--header-container{max-width:580px}.community--header-join{font-family:roboto,sans-serif!important;font-size:24px!important;line-height:1.5!important}.community--accordion-container{margin:40px 0}.community--committers-header{font-size:36px!important;line-height:1.22!important;margin-top:60px}.community--committers-header.large-margin{margin-top:60px;margin-bottom:40px}.community--button-container{margin-top:20px}}.install .page-subtitle{margin-bottom:45px}.install--headers-wrapper{max-width:936px;margin:0 auto}.install--description{text-align:center;margin:45px 0 60px}.install--description a{color:#017cee;text-decoration:underline}.install__accordions--wrapper{max-width:900px;margin:60px auto}.install__accordions-content--header{font-weight:500}.install__accordions-content--list-wrapper{margin-bottom:40px}.install__accordions-content--methods-wrapper{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-bottom:20px}.install__accordions-content--method-box{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:270px;height:160px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;border:solid 1px #cbcbcb;border-radius:5px;margin-right:40px}@media(max-width:1280px){.install .page-subtitle{margin-bottom:30px}.install--headers-wrapper{max-width:580px}.install--description{margin-top:30px;margin-bottom:30px}.install__accordions--wrapper{max-width:580px;margin-top:40px;margin-bottom:0}}@media(max-width:640px){.install__accordions-content--methods-wrapper{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;margin-bottom:0;margin-right:-36px}.install__accordions-content--method-box{margin-right:0;margin-bottom:20px}}footer{min-height:unset}footer .footer-section{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}footer .footer-section__media-section{padding:60px 60px 30px;background-color:#51504f}footer .footer-section__media-section--link{margin-right:30px}footer .footer-section__media-section--button-with-text{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}footer .footer-section__media-section--text{margin-right:20px}footer .footer-section__policies-section{padding:30px 60px;background-color:#636365;font-size:12px;-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}footer .footer-section__policies-section span{font-size:12px}footer .footer-section__policies-section--policies{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}footer .footer-section__policies-section--policy-item::before{content:"\00a0\00a0"}footer .footer-section__policies-section--policy-item::after{content:"\00a0\00a0|";color:#fff}footer .footer-section__policies-section--policy-item:last-of-type::after{content:"\00a0\00a0|\00a0\00a0"}footer .footer-section__policies-section--disclaimer{display:block;max-width:600px;color:#cbcbcb!important;margin-top:16px}@media(min-width:1920px){footer .footer-section__policies-section--disclaimer{max-width:800px}}footer .dropdown-toggle::after{color:#fff;vertical-align:middle}@media(max-width:1280px){footer .footer-section{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start}footer .footer-section span{font-size:14px!important;line-height:1.57!important}footer .footer-section__media-section{padding:30px 40px}footer .footer-section__media-section svg{height:31px;width:auto}footer .footer-section__media-section--link{margin-right:20px}footer .footer-section__media-section--button-with-text{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;margin-bottom:47px}footer .footer-section__media-section--text{margin-right:0;margin-bottom:16px}footer .footer-section__policies-section{padding:30px 40px}footer .footer-section__policies-section--policies{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}footer .footer-section__policies-section--policy-item::before,footer .footer-section__policies-section--policy-item::after,footer .footer-section__policies-section--policy-item:last-of-type::before,footer .footer-section__policies-section--policy-item:last-of-type::after{content:""}footer .footer-section__policies-section--language-toggle{margin:17px 0 35px}}.navbar{position:fixed;top:0;width:100%;background-color:#fff;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start;border-bottom:solid 1px #cbcbcb;z-index:32;padding:30px 60px}.navbar__menu-container{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1}.navbar__menu-content{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding-top:16px;padding-left:88px}.navbar__links-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.navbar__text-link{margin-right:30px;position:relative;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.navbar__text-link::before,.navbar__text-link::after{content:"";position:absolute;top:100%;width:0;right:0;height:2px;background-color:#017cee;-webkit-transition:.2s ease-out;-o-transition:.2s ease-out;transition:.2s ease-out}.navbar__text-link:hover,.navbar__text-link.active{color:#51504f}.navbar__text-link:hover::before,.navbar__text-link:hover::after,.navbar__text-link.active::before,.navbar__text-link.active::after{width:100%;left:0}.navbar--box-shadow{-webkit-box-shadow:0 2px 6px 0 rgba(0,0,0,.12);box-shadow:0 2px 6px 0 rgba(0,0,0,.12)}@media(max-width:1280px){.navbar{padding:20px}.navbar__icon-container svg{width:93px;height:auto}.navbar__menu-content{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;padding-left:0;padding-top:0}.navbar__drawer-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end}.navbar__toggle-button{border:none;background:0 0;padding:0;position:relative;width:26px;height:20px}.navbar__toggle-button--icon{position:absolute;top:0;bottom:0;left:0;right:0;visibility:hidden;opacity:0;-webkit-transition:.2s ease-out;-o-transition:.2s ease-out;transition:.2s ease-out}.navbar__toggle-button--icon.visible{visibility:visible;opacity:1}.navbar__drawer{position:fixed;top:77px;left:0;width:100%;height:-webkit-calc(100% - 77px);height:calc(100% - 77px);background-color:#fff;-webkit-transform:translateX(100%);-ms-transform:translateX(100%);-o-transform:translateX(100%);transform:translateX(100%);-webkit-transition:.2s ease-out;-o-transition:.2s ease-out;transition:.2s ease-out;padding:40px 40px 30px}.navbar__drawer--open{-webkit-transform:translateX(0);-ms-transform:translateX(0);-o-transform:translateX(0);transform:translateX(0)}.navbar__links-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.navbar__text-link{margin-right:0;margin-bottom:10px}.navbar__text-link:last-child{margin-bottom:20px}}#header{position:relative;margin:123px -20px 0;min-height:-webkit-calc(100vh - 123px);min-height:calc(100vh - 123px)}#header-canvas{padding:0;margin:0;position:absolute;width:100%;height:100%;top:0;left:0;right:0;bottom:0}#header-canvas .text-area{max-width:706px;width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);-o-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}#header-canvas .text-area--header{text-align:center;margin-bottom:20px}#header-canvas .text-area--subheader{font-weight:400!important;text-align:center;margin-bottom:20px}#header-canvas canvas{position:absolute;top:0;left:0;width:100%;height:100%;z-index:-1}@media(min-width:1920px){#header-canvas .text-area--header{font-size:90px}}@media(max-width:1280px){#header{margin:77px -20px 0;min-height:-webkit-calc(100vh - 77px);min-height:calc(100vh - 77px)}#header-canvas .text-area{max-width:450px}#header-canvas .text-area--header{margin-bottom:14px}#header-canvas .text-area--subheader{margin-bottom:26px}}@media(max-width:640px){#header-canvas .text-area{max-width:290px}#header-canvas .text-area--header{font-size:48px!important;line-height:1.25!important}#header-canvas .text-area--subheader{font-size:16px!important;line-height:1.63!important}}.roadmap{margin-top:40px}.roadmap main{padding-left:40px}.roadmap .breadcrumb{padding-bottom:0;margin-bottom:30px}.roadmap .breadcrumb-item+.breadcrumb-item{padding-left:4px}.roadmap .breadcrumb-item+.breadcrumb-item::before{color:#707070;padding-right:0}.roadmap .td-sidebar{position:-webkit-sticky;position:sticky;top:163px;height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;max-height:-webkit-calc(100vh - 163px);max-height:calc(100vh - 163px);max-width:270px;min-width:270px;width:100%;overflow-y:auto;padding-top:12px;padding-left:15px;padding-bottom:30px;margin-left:40px;background-color:#f9f9f9;border:none}.roadmap .td-sidebar::-webkit-scrollbar{-webkit-appearance:none}.roadmap .td-sidebar::-webkit-scrollbar-thumb{border-radius:8px;border:2px solid #fff;background-color:rgba(0,0,0,.5)}.roadmap .td-sidebar::-webkit-scrollbar:vertical{width:9px}.roadmap .td-sidebar__inner{position:static;height:unset}.roadmap .td-sidebar li>a{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.roadmap .td-sidebar li>a.active{color:#017cee}.roadmap .td-sidebar .searchb-box{margin-bottom:26px}.roadmap .td-sidebar .searchb-box .search-form{width:100%}.roadmap .td-sidebar .toctree li{list-style:none;font-family:roboto,sans-serif;font-size:16px;font-weight:400;font-stretch:normal;font-style:normal;line-height:1.63;letter-spacing:normal;color:#707070}.roadmap .td-sidebar .toctree ul{padding-left:15px;display:none}.roadmap .td-sidebar .toctree>ul,.roadmap .td-sidebar .toctree li.current>ul{display:block}.roadmap .td-sidebar .toctree .caption{font-family:roboto,sans-serif;font-size:18px;font-weight:700;font-stretch:normal;font-style:normal;line-height:1.33;letter-spacing:normal;color:#51504f;padding-bottom:13px;text-transform:uppercase;margin-bottom:0}.roadmap .td-sidebar .toctree .current{color:#017cee;font-weight:500}.roadmap .td-sidebar .toctree .current>a:not([href="#"]){color:#017cee}.roadmap .td-sidebar .toctree a .toctree-expand{display:inline-block;position:relative;height:1em}.roadmap .td-sidebar .toctree a .toctree-expand::before{position:absolute;top:6px;left:-12px;content:'►';font-size:7px}.roadmap .td-sidebar .toctree .current>a>.toctree-expand:before{content:'▼'}.roadmap .td-sidebar-nav__section{padding-right:0}.roadmap .td-sidebar-nav>.td-sidebar-nav__section .td-sidebar-nav__section{list-style:none;position:relative;margin-left:10px}.roadmap .td-sidebar-nav>.td-sidebar-nav__section .td-sidebar-nav__section::before{content:'►';position:absolute;top:6px;left:-12px;font-size:8px;color:#51504f}.roadmap .td-sidebar-nav>.td-sidebar-nav__section .td-sidebar-nav__section>ul{display:none}.roadmap .td-sidebar-nav>.td-sidebar-nav__section .td-sidebar-nav__section.current-section::before{content:'▼'}.roadmap .td-sidebar-nav>.td-sidebar-nav__section .td-sidebar-nav__section.current-section>ul{display:block}.roadmap .wy-nav-side-toc{position:-webkit-sticky;position:sticky;top:163px;overflow-x:hidden;overflow-y:auto;width:280px;height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;max-height:-webkit-calc(100vh - 163px);max-height:calc(100vh - 163px);font-size:14px;line-height:1.43}.roadmap .wy-nav-side-toc::-webkit-scrollbar{-webkit-appearance:none}.roadmap .wy-nav-side-toc::-webkit-scrollbar-thumb{border-radius:8px;border:2px solid #fff;background-color:rgba(0,0,0,.5)}.roadmap .wy-nav-side-toc::-webkit-scrollbar:vertical{width:9px}.roadmap .wy-nav-side-toc ul,.roadmap .wy-nav-side-toc ol{padding:0;list-style:none none}.roadmap .wy-nav-side-toc li{list-style:none}.roadmap .wy-nav-side-toc .wy-menu-vertical>ul,.roadmap .wy-nav-side-toc .wy-menu-vertical li.current>ul{padding-left:1px}.roadmap .wy-nav-side-toc .wy-menu-vertical a{display:inline-block;padding:.4045em 0;color:#707070}.roadmap .wy-nav-side-toc .wy-menu-vertical li a{border-left:solid 2px #cbcbcb;padding-left:-webkit-calc(1.25em + 1px);padding-left:calc(1.25em + 1px)}.roadmap .wy-nav-side-toc .wy-menu-vertical li.current{margin-left:-1px}.roadmap .wy-nav-side-toc .wy-menu-vertical li.current>a{border-left:solid 4px #017cee;color:#017cee}.roadmap .wy-nav-side-toc .wy-menu-vertical li li>a{padding-left:2.427em}.roadmap .wy-nav-side-toc .wy-menu-vertical li li li>a{padding-left:4.045em}.roadmap .wy-nav-side-toc .wy-menu-vertical li li li li>a{padding-left:5.663em}@media(max-width:1280px){.roadmap main{padding-left:0}.roadmap .td-sidebar{position:static;background-color:transparent;padding:0;margin:0;max-width:unset;height:530px}}.search-form{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:344px;padding:8px 20px;border:solid 1px #cbcbcb;border-radius:5px;margin:60px auto 0}.search-form__input{font-family:roboto,sans-serif;font-size:16px;color:#707070;line-height:1.63;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;padding-right:10px;border:none;background:0 0;outline:none;float:left}.search-form__button{border:none;background-color:transparent;padding:0}@media(max-width:1280px){.search-form{width:270px;padding:3px 20px;margin-top:30px}}.rating-container{margin-top:40px}.rating{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.rate-star{cursor:pointer;margin-right:13px}.rate-star svg path{fill:none;stroke:#51504f}.rate-star:hover svg path,.rate-star:hover~.rate-star svg path{fill:#017cee;stroke:none}.rst-content{color:#707070}.rst-content h1{margin-top:0;margin-bottom:30px;font-weight:500;font-family:rubik,sans-serif;color:#51504f;font-size:225%}.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6,.rst-content p{font-family:roboto,sans-serif;color:#707070}.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-top:40px;margin-bottom:20px;font-weight:500}.rst-content p{line-height:1.63;margin:0 0 30px;font-size:16px;overflow-wrap:break-word}.rst-content h2{font-size:150%}.rst-content h3{font-size:125%}.rst-content h4{font-size:115%}.rst-content h5{font-size:110%}.rst-content h6{font-size:100%}.rst-content code{max-width:100%;color:#51504f;padding:0 5px;font-family:roboto mono,monospace;overflow-x:auto}.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .admonition-todo,.rst-content .admonition{padding:9px 10px;line-height:24px;margin-bottom:24px;background:#e7f2fa}@media(max-width:768px){.rst-content .admonition p:not(.admonition-title){font-size:12px;line-height:1.83}}.rst-content .admonition-title:before{content:"!";background-color:#fff;border-radius:50%;padding:0 4px;margin-right:5px}.rst-content .admonition-title{color:#fff;font-weight:500;font-size:10px;line-height:2.1;display:block;background:#68d1ff;margin:-10px;padding:0 12px;margin-bottom:9px}.rst-content .danger,.rst-content .error{background:#fdece9}.rst-content .danger::before,.rst-content .error::before{color:#fdece9}.rst-content .danger .admonition-title,.rst-content .error .admonition-title{background:#ee8170}.rst-content .danger .admonition-title::before,.rst-content .error .admonition-title::before{color:#ee8170}.rst-content .attention,.rst-content .caution{background:#fff8f6}.rst-content .warning{background:#f8f8f8}.rst-content .attention .admonition-title,.rst-content .caution .admonition-title{background:#ffa996}.rst-content .attention .admonition-title::before,.rst-content .caution .admonition-title::before{color:#ffa996}.rst-content .warning .admonition-title{background:#a6a6a6}.rst-content .warning .admonition-title::before{color:#a6a6a6}.rst-content .note,.rst-content .seealso{background:#f3fbff}.rst-content .note .admonition-title,.rst-content .seealso .admonition-title{background:#68d2fe}.rst-content .note .admonition-title::before,.rst-content .seealso .admonition-title::before{color:#68d2fe}.rst-content .hint{background:#f2fef6}.rst-content .important{background:#e6f9fc}.rst-content .tip{background:#e5f7ec}.rst-content .hint .admonition-title{background:#63e598}.rst-content .hint .admonition-title::before{color:#63e598}.rst-content .important .admonition-title{background:#5bdae3}.rst-content .important .admonition-title::before{color:#5bdae3}.rst-content .tip .admonition-title{background:#5bcb88}.rst-content .tip .admonition-title::before{color:#5bcb88}.rst-content .note p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.rst-content .seealso p:last-child,.rst-content .admonition p:last-child{margin-bottom:0}.rst-content img{max-width:100%;height:auto}.rst-content div.figure{margin-bottom:24px}.rst-content div.figure p.caption{font-style:italic}.rst-content div.figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center{text-align:center}.rst-content .section>img,.rst-content .section>a>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre{background-color:#f2f8fe}.rst-content pre.literal-block,.rst-content .linenodiv pre{font-family:roboto mono,monospace;font-size:12px;line-height:1.4}@media print{.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol p,.rst-content .section ul p{margin-bottom:12px}.rst-content .section ol li p:last-child,.rst-content .section ul li p:last-child{margin-bottom:0}.rst-content .section ol p:last-child,.rst-content .section ul p:last-child{margin-bottom:24px}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:inherit}.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content .toctree-wrapper p.caption .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink,.rst-content .code-block-caption .headerlink{visibility:hidden;font-size:0}.rst-content h1 .headerlink:after,.rst-content h2 .headerlink:after,.rst-content .toctree-wrapper p.caption .headerlink:after,.rst-content h3 .headerlink:after,.rst-content h4 .headerlink:after,.rst-content h5 .headerlink:after,.rst-content h6 .headerlink:after,.rst-content dl dt .headerlink:after,.rst-content p.caption .headerlink:after,.rst-content table>caption .headerlink:after,.rst-content .code-block-caption .headerlink:after{content:url(/images/anchor.svg);vertical-align:bottom;padding-left:8px}.rst-content h1:hover .headerlink:after,.rst-content h2:hover .headerlink:after,.rst-content .toctree-wrapper p.caption:hover .headerlink:after,.rst-content h3:hover .headerlink:after,.rst-content h4:hover .headerlink:after,.rst-content h5:hover .headerlink:after,.rst-content h6:hover .headerlink:after,.rst-content dl dt:hover .headerlink:after,.rst-content p.caption:hover .headerlink:after,.rst-content table>caption:hover .headerlink:after,.rst-content .code-block-caption:hover .headerlink:after{visibility:visible}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .footnote-reference,.rst-content .citation-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content table.docutils,.rst-content table.field-list{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption{padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list th{margin:0;overflow:visible}.rst-content table.docutils td{padding:10px 31px}.rst-content table.docutils th,.rst-content table.field-list th{padding:11px 31px}.rst-content table.docutils td:first-child,.rst-content table.field-list td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead{text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th{border-bottom:solid 1px rgba(81,80,79,.3);border-left:solid 1px rgba(81,80,79,.3)}.rst-content table.docutils thead th p,.rst-content table.field-list thead th p{font-weight:700;font-size:18px;color:#51504f;line-height:1.33;margin-bottom:0}.rst-content table.docutils td,.rst-content table.field-list td{background-color:transparent;vertical-align:middle}.rst-content td p:last-child,.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child{margin-bottom:0}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td{background-color:rgba(112,112,112,.05)}.rst-content table.docutils{border:1px solid rgba(81,80,79,.3)}.rst-content table.docutils td{border-bottom:1px solid rgba(81,80,79,.3);border-left:1px solid rgba(81,80,79,.3)}.rst-content table.docutils tbody>tr:last-child td{border-bottom-width:0}.rst-content .wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.rst-content .wy-table-responsive table{margin-bottom:0!important}.rst-content .wy-table-responsive table td,.rst-content .wy-table-responsive table th{white-space:nowrap}.rst-content code big,.rst-content tt em,.rst-content code em{font-size:100%!important;line-height:normal}.rst-content code.literal{color:#e74c3c}.rst-content code.xref,.rst-content a code{font-weight:700;color:#707070}.rst-content pre,.rst-content kbd{font-family:roboto mono,monospace}.rst-content kbd{background-color:inherit;color:inherit;-webkit-box-shadow:none;box-shadow:none;border:none;font-size:100%}.rst-content a code{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px;word-break:break-word}.rst-content dl p,.rst-content dl table,.rst-content dl ul,.rst-content dl ol{margin-bottom:12px!important}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl:not(.docutils){margin-bottom:24px}.rst-content dl:not(.docutils) dt{font-family:roboto mono,monospace;display:table;margin:6px 0;font-size:100%;line-height:1.63;background:#f3fbff;color:#51504f;border-top:solid 4px #68d1ff;padding:8px 10px;position:relative}@media(max-width:768px){.rst-content dl:not(.docutils) dt{font-size:10px}}.rst-content dl:not(.docutils) dt:before{color:#68d1ff}.rst-content dl:not(.docutils) dt .headerlink{color:#707070;font-size:100%!important}.rst-content dl:not(.docutils) dt .fn-backref{color:#0cb6ff}.rst-content dl:not(.docutils) dl dt{margin-bottom:6px;border:none;border-left:solid 8px #a6a6a6;background:#f8f8f8;color:#707070}.rst-content dl:not(.docutils) dl dt .headerlink{color:#707070;font-size:100%!important}.rst-content dl:not(.docutils) dt:first-child{margin-top:0}.rst-content dl:not(.docutils) code{font-weight:700}.rst-content dl:not(.docutils) code.descname,.rst-content dl:not(.docutils) code.descclassname{background-color:transparent;border:none;padding:0;font-size:100%!important}.rst-content dl:not(.docutils) code.descname{font-weight:700}.rst-content dl:not(.docutils) .optional{display:inline-block;padding:0 4px;color:#51504f;font-weight:700}.rst-content dl:not(.docutils) .property{display:inline-block;padding-right:8px}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content .versionmodified{font-style:italic}.rst-content .example-header{position:relative;background:#017cee;padding:8px 16px;margin-bottom:0}.rst-content .example-block-wrapper pre{margin:0;width:unset;border-top-left-radius:0;border-top-right-radius:0}.rst-content .example-header--with-button{padding-right:166px}@media(max-width:768px){.rst-content .example-header--with-button{padding-right:100px}}.rst-content .example-header:after{content:'';display:table;clear:both}.rst-content .example-title{display:block;padding:4px;margin-right:16px;color:#fff;overflow-x:auto}@media(max-width:768px){.rst-content .example-title{overflow-wrap:initial;font-size:12px}}.rst-content .example-header-button{top:8px;right:16px;position:absolute}.rst-content .example-header+.highlight-python{margin-top:0!important}.rst-content .viewcode-button{display:inline-block;padding:8px 16px;border:0;margin:0;color:#fff;font-weight:700;line-height:1;text-decoration:underline;text-overflow:ellipsis;overflow:hidden;text-transform:lowercase;vertical-align:middle;white-space:nowrap}@media(max-width:768px){.rst-content .viewcode-button{font-size:12px;padding:7px 0}}.rst-content .viewcode-button:visited{color:#404040}.rst-content .viewcode-button:hover,.rst-content .viewcode-button:focus{color:#404040}@media(min-width:1024px){.rst-content .section::before{display:block;content:" ";margin-top:-83px;height:83px;visibility:hidden}}.content-drawer-wrapper{display:none}@media(max-width:1280px){.content-drawer-wrapper{display:block;margin-bottom:30px}}.content-drawer-wrapper .navbar{-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;left:0}.content-drawer-wrapper .navbar--hidden{display:none}.content-drawer-container{position:fixed;top:77px;left:0;width:100%;height:100%;background-color:#fff;-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);-o-transform:translateX(-100%);transform:translateX(-100%);-webkit-transition:.2s ease-out;-o-transition:.2s ease-out;transition:.2s ease-out;z-index:100}.content-drawer-container--open{-webkit-transform:translateX(0);-ms-transform:translateX(0);-o-transform:translateX(0);transform:translateX(0)}.content-drawer{padding:20px 40px}.content-drawer__toggle-button{border:none;background:0 0;padding:0;position:relative;width:26px;height:20px}.content-drawer__toggle-button--icon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;visibility:hidden;opacity:0;-webkit-transition:.2s ease-out;-o-transition:.2s ease-out;transition:.2s ease-out}.content-drawer__toggle-button--icon svg{margin-right:10px}.content-drawer__toggle-button--icon.visible{visibility:visible;opacity:1}.dropdown-menu{font-family:roboto,sans-serif}.dropdown-toggle::after{color:#51504f}.sidebar__version-selector{margin-bottom:22px}.chroma,.highlight{background-color:#fff}.chroma .lntd,.highlight .lntd{vertical-align:top;padding:0;margin:0;border:0}.chroma .lntable,.highlight .lntable{border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block}.chroma .hl,.highlight .hl{display:block;width:100%;background-color:#ffc}.chroma .lnt,.chroma .ln,.highlight .lnt,.highlight .ln{margin-right:.4em;padding:0 .4em;color:#7f7f7f}.chroma .k,.chroma .kc,.chroma .kd,.chroma .kn,.chroma .kp,.chroma .kr,.highlight .k,.highlight .kc,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr{color:#00f}.chroma .kt,.chroma .nc,.highlight .kt,.highlight .nc{color:#2b91af}.chroma .s,.chroma .sa,.chroma .sb,.chroma .sc,.chroma .dl,.chroma .sd,.chroma .s2,.chroma .se,.chroma .sh,.chroma .si,.chroma .sx,.chroma .sr,.chroma .s1,.chroma .ss,.highlight .s,.highlight .sa,.highlight .sb,.highlight .sc,.highlight .dl,.highlight .sd,.highlight .s2,.highlight .se,.highlight .sh,.highlight .si,.highlight .sx,.highlight .sr,.highlight .s1,.highlight .ss{color:#a31515}.chroma .ow,.highlight .ow{color:#00f}.chroma .c,.chroma .ch,.chroma .cm,.chroma .c1,.chroma .cs,.highlight .c,.highlight .ch,.highlight .cm,.highlight .c1,.highlight .cs{color:green}.chroma .cp,.chroma .cpf,.highlight .cp,.highlight .cpf{color:#00f}.chroma .ge,.highlight .ge{font-style:italic}.chroma .gh,.chroma .gp,.chroma .gs,.chroma .gu,.highlight .gh,.highlight .gp,.highlight .gs,.highlight .gu{font-weight:700}pre{margin:40px 0;padding:16px 20px;border:solid 1px #cbcbcb;border-radius:5px;width:100%}.share-section--icons-wrapper{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.share-section--icon{margin-right:12px;cursor:pointer}.four-oh-four{height:-webkit-calc(100vh - 123px);height:calc(100vh - 123px);position:relative}.four-oh-four__text-container{position:relative;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);-o-transform:translate(-50%,-50%);transform:translate(-50%,-50%);text-align:center} \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/_gen/css/main.min.css b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/_gen/css/main.min.css new file mode 100644 index 00000000000..603f3cb39ff --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/_gen/css/main.min.css @@ -0,0 +1,7 @@ +@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,700,700i";@fa-font-path:"../webfonts";/*!* Bootstrap v4.1.3 (https://getbootstrap.com/) +* Copyright 2011-2018 The Bootstrap Authors +* Copyright 2011-2018 Twitter, Inc. +* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)*/:root{--blue: #72A1E5;--indigo: #6610f2;--purple: #6f42c1;--pink: #e83e8c;--red: #dc3545;--orange: #BA5A31;--yellow: #ffc107;--green: #28a745;--teal: #20c997;--cyan: #17a2b8;--white: #fff;--gray: #888;--gray-dark: #333;--primary: #30638E;--secondary: #FFA630;--success: #3772FF;--info: #C0E0DE;--warning: #ED6A5A;--danger: #ED6A5A;--light: #D3F3EE;--dark: #403F4C;--breakpoint-xs: 0;--breakpoint-sm: 576px;--breakpoint-md: 768px;--breakpoint-lg: 992px;--breakpoint-xl: 1200px;--font-family-sans-serif: "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}*,*::before,*::after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:rgba(0,0,0,0)}@-ms-viewport{width:device-width;}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:open sans,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;font-size:1rem;font-weight:400;line-height:1.5;color:#222;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[title],abbr[data-original-title]{text-decoration:underline;-webkit-text-decoration:underline dotted;-moz-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#3176d9;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#1e53a0;text-decoration:none}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):hover,a:not([href]):not([tabindex]):focus{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}pre,code,kbd,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,liberation mono,courier new,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#888;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}button,html [type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{padding:0;border-style:none}input[type=radio],input[type=checkbox]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{margin-bottom:.5rem;font-family:inherit;font-weight:500;line-height:1.2;color:inherit}h1,.h1{font-size:2.25rem}h2,.h2{font-size:2rem}h3,.h3{font-size:1.5rem}h4,.h4{font-size:1.35rem}h5,.h5{font-size:1.15rem}h6,.h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:3rem;font-weight:700;line-height:1.2}.display-2{font-size:2.5rem;font-weight:700;line-height:1.2}.display-3{font-size:2rem;font-weight:700;line-height:1.2}.display-4{font-size:1.75rem;font-weight:700;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}small,.small{font-size:80%;font-weight:400}mark,.mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#888}.blockquote-footer::before{content:"\2014 \00A0"}.img-fluid,.td-content img{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075);max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#888}code{font-size:87.5%;color:#c97300;word-break:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#222;border-radius:.2rem;-webkit-box-shadow:inset 0 -.1rem 0 rgba(0,0,0,.25);box-shadow:inset 0 -.1rem 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;font-size:87.5%;color:#222}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media(min-width:576px){.container{max-width:540px}}@media(min-width:768px){.container{max-width:720px}}@media(min-width:992px){.container{max-width:960px}}@media(min-width:1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-11,.col-12,.col,.col-auto,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm,.col-sm-auto,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-md,.col-md-auto,.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg,.col-lg-auto,.col-xl-1,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl,.col-xl-auto{position:relative;width:100%;min-height:1px;padding-right:15px;padding-left:15px}.col{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333333%;-ms-flex:0 0 8.33333333%;flex:0 0 8.33333333%;max-width:8.33333333%}.col-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66666667%;-ms-flex:0 0 16.66666667%;flex:0 0 16.66666667%;max-width:16.66666667%}.col-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333333%;-ms-flex:0 0 33.33333333%;flex:0 0 33.33333333%;max-width:33.33333333%}.col-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66666667%;-ms-flex:0 0 41.66666667%;flex:0 0 41.66666667%;max-width:41.66666667%}.col-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333333%;-ms-flex:0 0 58.33333333%;flex:0 0 58.33333333%;max-width:58.33333333%}.col-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66666667%;-ms-flex:0 0 66.66666667%;flex:0 0 66.66666667%;max-width:66.66666667%}.col-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333333%;-ms-flex:0 0 83.33333333%;flex:0 0 83.33333333%;max-width:83.33333333%}.col-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66666667%;-ms-flex:0 0 91.66666667%;flex:0 0 91.66666667%;max-width:91.66666667%}.col-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.order-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.order-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.order-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.order-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.order-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.order-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.order-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.order-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.order-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.order-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.order-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.order-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.order-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.order-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}@media(min-width:576px){.col-sm{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-sm-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333333%;-ms-flex:0 0 8.33333333%;flex:0 0 8.33333333%;max-width:8.33333333%}.col-sm-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66666667%;-ms-flex:0 0 16.66666667%;flex:0 0 16.66666667%;max-width:16.66666667%}.col-sm-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333333%;-ms-flex:0 0 33.33333333%;flex:0 0 33.33333333%;max-width:33.33333333%}.col-sm-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66666667%;-ms-flex:0 0 41.66666667%;flex:0 0 41.66666667%;max-width:41.66666667%}.col-sm-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333333%;-ms-flex:0 0 58.33333333%;flex:0 0 58.33333333%;max-width:58.33333333%}.col-sm-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66666667%;-ms-flex:0 0 66.66666667%;flex:0 0 66.66666667%;max-width:66.66666667%}.col-sm-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333333%;-ms-flex:0 0 83.33333333%;flex:0 0 83.33333333%;max-width:83.33333333%}.col-sm-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66666667%;-ms-flex:0 0 91.66666667%;flex:0 0 91.66666667%;max-width:91.66666667%}.col-sm-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.order-sm-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.order-sm-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.order-sm-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.order-sm-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.order-sm-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.order-sm-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.order-sm-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.order-sm-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.order-sm-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.order-sm-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.order-sm-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.order-sm-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.order-sm-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.order-sm-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}}@media(min-width:768px){.col-md{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-md-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333333%;-ms-flex:0 0 8.33333333%;flex:0 0 8.33333333%;max-width:8.33333333%}.col-md-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66666667%;-ms-flex:0 0 16.66666667%;flex:0 0 16.66666667%;max-width:16.66666667%}.col-md-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333333%;-ms-flex:0 0 33.33333333%;flex:0 0 33.33333333%;max-width:33.33333333%}.col-md-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66666667%;-ms-flex:0 0 41.66666667%;flex:0 0 41.66666667%;max-width:41.66666667%}.col-md-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333333%;-ms-flex:0 0 58.33333333%;flex:0 0 58.33333333%;max-width:58.33333333%}.col-md-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66666667%;-ms-flex:0 0 66.66666667%;flex:0 0 66.66666667%;max-width:66.66666667%}.col-md-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333333%;-ms-flex:0 0 83.33333333%;flex:0 0 83.33333333%;max-width:83.33333333%}.col-md-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66666667%;-ms-flex:0 0 91.66666667%;flex:0 0 91.66666667%;max-width:91.66666667%}.col-md-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.order-md-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.order-md-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.order-md-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.order-md-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.order-md-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.order-md-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.order-md-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.order-md-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.order-md-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.order-md-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.order-md-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.order-md-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.order-md-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.order-md-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}}@media(min-width:992px){.col-lg{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-lg-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333333%;-ms-flex:0 0 8.33333333%;flex:0 0 8.33333333%;max-width:8.33333333%}.col-lg-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66666667%;-ms-flex:0 0 16.66666667%;flex:0 0 16.66666667%;max-width:16.66666667%}.col-lg-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333333%;-ms-flex:0 0 33.33333333%;flex:0 0 33.33333333%;max-width:33.33333333%}.col-lg-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66666667%;-ms-flex:0 0 41.66666667%;flex:0 0 41.66666667%;max-width:41.66666667%}.col-lg-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333333%;-ms-flex:0 0 58.33333333%;flex:0 0 58.33333333%;max-width:58.33333333%}.col-lg-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66666667%;-ms-flex:0 0 66.66666667%;flex:0 0 66.66666667%;max-width:66.66666667%}.col-lg-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333333%;-ms-flex:0 0 83.33333333%;flex:0 0 83.33333333%;max-width:83.33333333%}.col-lg-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66666667%;-ms-flex:0 0 91.66666667%;flex:0 0 91.66666667%;max-width:91.66666667%}.col-lg-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.order-lg-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.order-lg-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.order-lg-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.order-lg-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.order-lg-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.order-lg-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.order-lg-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.order-lg-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.order-lg-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.order-lg-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.order-lg-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.order-lg-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.order-lg-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.order-lg-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}}@media(min-width:1200px){.col-xl{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-xl-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333333%;-ms-flex:0 0 8.33333333%;flex:0 0 8.33333333%;max-width:8.33333333%}.col-xl-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66666667%;-ms-flex:0 0 16.66666667%;flex:0 0 16.66666667%;max-width:16.66666667%}.col-xl-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333333%;-ms-flex:0 0 33.33333333%;flex:0 0 33.33333333%;max-width:33.33333333%}.col-xl-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66666667%;-ms-flex:0 0 41.66666667%;flex:0 0 41.66666667%;max-width:41.66666667%}.col-xl-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333333%;-ms-flex:0 0 58.33333333%;flex:0 0 58.33333333%;max-width:58.33333333%}.col-xl-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66666667%;-ms-flex:0 0 66.66666667%;flex:0 0 66.66666667%;max-width:66.66666667%}.col-xl-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333333%;-ms-flex:0 0 83.33333333%;flex:0 0 83.33333333%;max-width:83.33333333%}.col-xl-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66666667%;-ms-flex:0 0 91.66666667%;flex:0 0 91.66666667%;max-width:91.66666667%}.col-xl-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.order-xl-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.order-xl-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.order-xl-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.order-xl-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.order-xl-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.order-xl-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.order-xl-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.order-xl-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.order-xl-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.order-xl-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.order-xl-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.order-xl-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.order-xl-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.order-xl-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}}.table,.td-box .row.section>table,.td-content>table{width:100%;margin-bottom:1rem;background-color:transparent}.table th,.td-box .row.section>table th,.td-content>table th,.table td,.td-box .row.section>table td,.td-content>table td{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th,.td-box .row.section>table thead th,.td-content>table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody,.td-box .row.section>table tbody+tbody,.td-content>table tbody+tbody{border-top:2px solid #dee2e6}.table .table,.td-box .row.section>table .table,.td-content>table .table,.table .td-box .row.section>table,.td-box .table .row.section>table,.td-box .row.section>table .row.section>table,.td-content>table .td-box .row.section>table,.td-box .td-content>table .row.section>table,.table .td-content>table,.td-box .row.section>table .td-content>table,.td-content>table .td-content>table{background-color:#fff}.table-sm th,.table-sm td{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered th,.table-bordered td{border:1px solid #dee2e6}.table-bordered thead th,.table-bordered thead td{border-bottom-width:2px}.table-borderless th,.table-borderless td,.table-borderless thead th,.table-borderless tbody+tbody{border:0}.table-striped tbody tr:nth-of-type(odd),.td-box .row.section>table tbody tr:nth-of-type(odd),.td-content>table tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>th,.table-primary>td{background-color:#c5d3df}.table-hover .table-primary:hover{background-color:#b5c7d6}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#b5c7d6}.table-secondary,.table-secondary>th,.table-secondary>td{background-color:#ffe6c5}.table-hover .table-secondary:hover{background-color:#ffdbac}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#ffdbac}.table-success,.table-success>th,.table-success>td{background-color:#c7d8ff}.table-hover .table-success:hover{background-color:#aec6ff}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#aec6ff}.table-info,.table-info>th,.table-info>td{background-color:#edf6f6}.table-hover .table-info:hover{background-color:#dceeee}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#dceeee}.table-warning,.table-warning>th,.table-warning>td{background-color:#fad5d1}.table-hover .table-warning:hover{background-color:#f8c0ba}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#f8c0ba}.table-danger,.table-danger>th,.table-danger>td{background-color:#fad5d1}.table-hover .table-danger:hover{background-color:#f8c0ba}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f8c0ba}.table-light,.table-light>th,.table-light>td{background-color:#f3fcfa}.table-hover .table-light:hover{background-color:#dff7f2}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#dff7f2}.table-dark,.table-dark>th,.table-dark>td{background-color:#cac9cd}.table-hover .table-dark:hover{background-color:#bdbcc1}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#bdbcc1}.table-active,.table-active>th,.table-active>td{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th,.td-box .row.section>table .thead-dark th,.td-content>table .thead-dark th{color:#fff;background-color:#222;border-color:#353535}.table .thead-light th,.td-box .row.section>table .thead-light th,.td-content>table .thead-light th{color:#495057;background-color:#eee;border-color:#dee2e6}.table-dark{color:#fff;background-color:#222}.table-dark th,.table-dark td,.table-dark thead th{border-color:#353535}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd),.td-box .row.section>table.table-dark tbody tr:nth-of-type(odd),.td-content>table.table-dark tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{background-color:rgba(255,255,255,.075)}@media(max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-sm>.table-bordered{border:0}}@media(max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-md>.table-bordered{border:0}}@media(max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-lg>.table-bordered{border:0}}@media(max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-xl>.table-bordered{border:0}}.table-responsive,.td-box .row.section>table,.td-content>table{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive>.table-bordered,.td-box .row.section>table>.table-bordered,.td-content>table>.table-bordered{border:0}.form-control{display:block;width:100%;height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px);padding:.375rem .75rem;font-size:1rem;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border-radius:.25rem;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media screen and (prefers-reduced-motion:reduce){.form-control{-webkit-transition:none;-o-transition:none;transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#6fa3ce;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(48,99,142,.25);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(48,99,142,.25)}.form-control::-webkit-input-placeholder{color:#888;opacity:1}.form-control::-moz-placeholder{color:#888;opacity:1}.form-control:-ms-input-placeholder{color:#888;opacity:1}.form-control::placeholder{color:#888;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#eee;opacity:1}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:-webkit-calc(0.375rem + 1px);padding-top:calc(0.375rem + 1px);padding-bottom:-webkit-calc(0.375rem + 1px);padding-bottom:calc(0.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:-webkit-calc(0.5rem + 1px);padding-top:calc(0.5rem + 1px);padding-bottom:-webkit-calc(0.5rem + 1px);padding-bottom:calc(0.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:-webkit-calc(0.25rem + 1px);padding-top:calc(0.25rem + 1px);padding-bottom:-webkit-calc(0.25rem + 1px);padding-bottom:calc(0.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding-top:.375rem;padding-bottom:.375rem;margin-bottom:0;line-height:1.5;color:#222;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{height:-webkit-calc(1.8125rem + 2px);height:calc(1.8125rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:-webkit-calc(2.875rem + 2px);height:calc(2.875rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[size],select.form-control[multiple]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label{color:#888}.form-check-label{margin-bottom:0}.form-check-inline{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#3772ff}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(55,114,255,.9);border-radius:.25rem}.was-validated .form-control:valid,.form-control.is-valid,.was-validated .custom-select:valid,.custom-select.is-valid{border-color:#3772ff}.was-validated .form-control:valid:focus,.form-control.is-valid:focus,.was-validated .custom-select:valid:focus,.custom-select.is-valid:focus{border-color:#3772ff;-webkit-box-shadow:0 0 0 .2rem rgba(55,114,255,.25);box-shadow:0 0 0 .2rem rgba(55,114,255,.25)}.was-validated .form-control:valid~.valid-feedback,.was-validated .form-control:valid~.valid-tooltip,.form-control.is-valid~.valid-feedback,.form-control.is-valid~.valid-tooltip,.was-validated .custom-select:valid~.valid-feedback,.was-validated .custom-select:valid~.valid-tooltip,.custom-select.is-valid~.valid-feedback,.custom-select.is-valid~.valid-tooltip{display:block}.was-validated .form-control-file:valid~.valid-feedback,.was-validated .form-control-file:valid~.valid-tooltip,.form-control-file.is-valid~.valid-feedback,.form-control-file.is-valid~.valid-tooltip{display:block}.was-validated .form-check-input:valid~.form-check-label,.form-check-input.is-valid~.form-check-label{color:#3772ff}.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip,.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip{display:block}.was-validated .custom-control-input:valid~.custom-control-label,.custom-control-input.is-valid~.custom-control-label{color:#3772ff}.was-validated .custom-control-input:valid~.custom-control-label::before,.custom-control-input.is-valid~.custom-control-label::before{background-color:#b7ccff}.was-validated .custom-control-input:valid~.valid-feedback,.was-validated .custom-control-input:valid~.valid-tooltip,.custom-control-input.is-valid~.valid-feedback,.custom-control-input.is-valid~.valid-tooltip{display:block}.was-validated .custom-control-input:valid:checked~.custom-control-label::before,.custom-control-input.is-valid:checked~.custom-control-label::before{background:#6a96ff -webkit-gradient(linear,left top,left bottom,from(#80a6ff),to(#6a96ff)) repeat-x;background:#6a96ff -webkit-linear-gradient(top,#80a6ff,#6a96ff) repeat-x;background:#6a96ff -o-linear-gradient(top,#80a6ff,#6a96ff) repeat-x;background:#6a96ff linear-gradient(180deg,#80a6ff,#6a96ff) repeat-x}.was-validated .custom-control-input:valid:focus~.custom-control-label::before,.custom-control-input.is-valid:focus~.custom-control-label::before{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(55,114,255,.25);box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(55,114,255,.25)}.was-validated .custom-file-input:valid~.custom-file-label,.custom-file-input.is-valid~.custom-file-label{border-color:#3772ff}.was-validated .custom-file-input:valid~.custom-file-label::after,.custom-file-input.is-valid~.custom-file-label::after{border-color:inherit}.was-validated .custom-file-input:valid~.valid-feedback,.was-validated .custom-file-input:valid~.valid-tooltip,.custom-file-input.is-valid~.valid-feedback,.custom-file-input.is-valid~.valid-tooltip{display:block}.was-validated .custom-file-input:valid:focus~.custom-file-label,.custom-file-input.is-valid:focus~.custom-file-label{-webkit-box-shadow:0 0 0 .2rem rgba(55,114,255,.25);box-shadow:0 0 0 .2rem rgba(55,114,255,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#ed6a5a}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(237,106,90,.9);border-radius:.25rem}.was-validated .form-control:invalid,.form-control.is-invalid,.was-validated .custom-select:invalid,.custom-select.is-invalid{border-color:#ed6a5a}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus,.was-validated .custom-select:invalid:focus,.custom-select.is-invalid:focus{border-color:#ed6a5a;-webkit-box-shadow:0 0 0 .2rem rgba(237,106,90,.25);box-shadow:0 0 0 .2rem rgba(237,106,90,.25)}.was-validated .form-control:invalid~.invalid-feedback,.was-validated .form-control:invalid~.invalid-tooltip,.form-control.is-invalid~.invalid-feedback,.form-control.is-invalid~.invalid-tooltip,.was-validated .custom-select:invalid~.invalid-feedback,.was-validated .custom-select:invalid~.invalid-tooltip,.custom-select.is-invalid~.invalid-feedback,.custom-select.is-invalid~.invalid-tooltip{display:block}.was-validated .form-control-file:invalid~.invalid-feedback,.was-validated .form-control-file:invalid~.invalid-tooltip,.form-control-file.is-invalid~.invalid-feedback,.form-control-file.is-invalid~.invalid-tooltip{display:block}.was-validated .form-check-input:invalid~.form-check-label,.form-check-input.is-invalid~.form-check-label{color:#ed6a5a}.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip,.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip{display:block}.was-validated .custom-control-input:invalid~.custom-control-label,.custom-control-input.is-invalid~.custom-control-label{color:#ed6a5a}.was-validated .custom-control-input:invalid~.custom-control-label::before,.custom-control-input.is-invalid~.custom-control-label::before{background-color:#fad2cd}.was-validated .custom-control-input:invalid~.invalid-feedback,.was-validated .custom-control-input:invalid~.invalid-tooltip,.custom-control-input.is-invalid~.invalid-feedback,.custom-control-input.is-invalid~.invalid-tooltip{display:block}.was-validated .custom-control-input:invalid:checked~.custom-control-label::before,.custom-control-input.is-invalid:checked~.custom-control-label::before{background:#f29488 -webkit-gradient(linear,left top,left bottom,from(#f4a49a),to(#f29488)) repeat-x;background:#f29488 -webkit-linear-gradient(top,#f4a49a,#f29488) repeat-x;background:#f29488 -o-linear-gradient(top,#f4a49a,#f29488) repeat-x;background:#f29488 linear-gradient(180deg,#f4a49a,#f29488) repeat-x}.was-validated .custom-control-input:invalid:focus~.custom-control-label::before,.custom-control-input.is-invalid:focus~.custom-control-label::before{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(237,106,90,.25);box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(237,106,90,.25)}.was-validated .custom-file-input:invalid~.custom-file-label,.custom-file-input.is-invalid~.custom-file-label{border-color:#ed6a5a}.was-validated .custom-file-input:invalid~.custom-file-label::after,.custom-file-input.is-invalid~.custom-file-label::after{border-color:inherit}.was-validated .custom-file-input:invalid~.invalid-feedback,.was-validated .custom-file-input:invalid~.invalid-tooltip,.custom-file-input.is-invalid~.invalid-feedback,.custom-file-input.is-invalid~.invalid-tooltip{display:block}.was-validated .custom-file-input:invalid:focus~.custom-file-label,.custom-file-input.is-invalid:focus~.custom-file-label{-webkit-box-shadow:0 0 0 .2rem rgba(237,106,90,.25);box-shadow:0 0 0 .2rem rgba(237,106,90,.25)}.form-inline{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media(min-width:576px){.form-inline label{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .input-group,.form-inline .custom-select{width:auto}.form-inline .form-check{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;text-align:center;white-space:nowrap;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media screen and (prefers-reduced-motion:reduce){.btn{-webkit-transition:none;-o-transition:none;transition:none}}.btn:hover,.btn:focus{text-decoration:none}.btn:focus,.btn.focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(48,99,142,.25);box-shadow:0 0 0 .2rem rgba(48,99,142,.25)}.btn.disabled,.btn:disabled{opacity:.65;-webkit-box-shadow:none;box-shadow:none}.btn:not(:disabled):not(.disabled){cursor:pointer}.btn:not(:disabled):not(.disabled):active,.btn:not(:disabled):not(.disabled).active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn:not(:disabled):not(.disabled):active:focus,.btn:not(:disabled):not(.disabled).active:focus{-webkit-box-shadow:0 0 0 .2rem rgba(48,99,142,.25),inset 0 3px 5px rgba(0,0,0,.125);box-shadow:0 0 0 .2rem rgba(48,99,142,.25),inset 0 3px 5px rgba(0,0,0,.125)}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x;border-color:#30638e;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-primary:hover{color:#fff;background:#264f71 -webkit-gradient(linear,left top,left bottom,from(#476987),to(#264f71)) repeat-x;background:#264f71 -webkit-linear-gradient(top,#476987,#264f71) repeat-x;background:#264f71 -o-linear-gradient(top,#476987,#264f71) repeat-x;background:#264f71 linear-gradient(180deg,#476987,#264f71) repeat-x;border-color:#234868}.btn-primary:focus,.btn-primary.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(48,99,142,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(48,99,142,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#30638e;border-color:#30638e}.btn-primary:not(:disabled):not(.disabled):active,.btn-primary:not(:disabled):not(.disabled).active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#234868;background-image:none;border-color:#20425e}.btn-primary:not(:disabled):not(.disabled):active:focus,.btn-primary:not(:disabled):not(.disabled).active:focus,.show>.btn-primary.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(48,99,142,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(48,99,142,.5)}.btn-secondary{color:#fff;background:#FFA630 -webkit-gradient(linear,left top,left bottom,from(#ffb34f),to(#FFA630)) repeat-x;background:#ffa630 -webkit-linear-gradient(top,#ffb34f,#FFA630) repeat-x;background:#ffa630 -o-linear-gradient(top,#ffb34f,#FFA630) repeat-x;background:#ffa630 linear-gradient(180deg,#ffb34f,#FFA630) repeat-x;border-color:#ffa630;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-secondary:hover{color:#fff;background:#ff960a -webkit-gradient(linear,left top,left bottom,from(#ffa52f),to(#ff960a)) repeat-x;background:#ff960a -webkit-linear-gradient(top,#ffa52f,#ff960a) repeat-x;background:#ff960a -o-linear-gradient(top,#ffa52f,#ff960a) repeat-x;background:#ff960a linear-gradient(180deg,#ffa52f,#ff960a) repeat-x;border-color:#fc9000}.btn-secondary:focus,.btn-secondary.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(255,166,48,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(255,166,48,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#ffa630;border-color:#ffa630}.btn-secondary:not(:disabled):not(.disabled):active,.btn-secondary:not(:disabled):not(.disabled).active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#fc9000;background-image:none;border-color:#ef8800}.btn-secondary:not(:disabled):not(.disabled):active:focus,.btn-secondary:not(:disabled):not(.disabled).active:focus,.show>.btn-secondary.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(255,166,48,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(255,166,48,.5)}.btn-success{color:#fff;background:#3772FF -webkit-gradient(linear,left top,left bottom,from(#5587ff),to(#3772FF)) repeat-x;background:#3772ff -webkit-linear-gradient(top,#5587ff,#3772FF) repeat-x;background:#3772ff -o-linear-gradient(top,#5587ff,#3772FF) repeat-x;background:#3772ff linear-gradient(180deg,#5587ff,#3772FF) repeat-x;border-color:#3772ff;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-success:hover{color:#fff;background:#1157ff -webkit-gradient(linear,left top,left bottom,from(#3470ff),to(#1157ff)) repeat-x;background:#1157ff -webkit-linear-gradient(top,#3470ff,#1157ff) repeat-x;background:#1157ff -o-linear-gradient(top,#3470ff,#1157ff) repeat-x;background:#1157ff linear-gradient(180deg,#3470ff,#1157ff) repeat-x;border-color:#044eff}.btn-success:focus,.btn-success.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(55,114,255,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(55,114,255,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#3772ff;border-color:#3772ff}.btn-success:not(:disabled):not(.disabled):active,.btn-success:not(:disabled):not(.disabled).active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#044eff;background-image:none;border-color:#0049f6}.btn-success:not(:disabled):not(.disabled):active:focus,.btn-success:not(:disabled):not(.disabled).active:focus,.show>.btn-success.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(55,114,255,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(55,114,255,.5)}.btn-info{color:#222;background:#C0E0DE -webkit-gradient(linear,left top,left bottom,from(#c9e5e3),to(#C0E0DE)) repeat-x;background:#c0e0de -webkit-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x;background:#c0e0de -o-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x;background:#c0e0de linear-gradient(180deg,#c9e5e3,#C0E0DE) repeat-x;border-color:#c0e0de;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-info:hover{color:#fff;background:#a6d3d1 -webkit-gradient(linear,left top,left bottom,from(#b4dad8),to(#a6d3d1)) repeat-x;background:#a6d3d1 -webkit-linear-gradient(top,#b4dad8,#a6d3d1) repeat-x;background:#a6d3d1 -o-linear-gradient(top,#b4dad8,#a6d3d1) repeat-x;background:#a6d3d1 linear-gradient(180deg,#b4dad8,#a6d3d1) repeat-x;border-color:#9ecfcc}.btn-info:focus,.btn-info.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(192,224,222,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(192,224,222,.5)}.btn-info.disabled,.btn-info:disabled{color:#222;background-color:#c0e0de;border-color:#c0e0de}.btn-info:not(:disabled):not(.disabled):active,.btn-info:not(:disabled):not(.disabled).active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#9ecfcc;background-image:none;border-color:#95cbc8}.btn-info:not(:disabled):not(.disabled):active:focus,.btn-info:not(:disabled):not(.disabled).active:focus,.show>.btn-info.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(192,224,222,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(192,224,222,.5)}.btn-warning{color:#fff;background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x;border-color:#ed6a5a;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-warning:hover{color:#fff;background:#e94b38 -webkit-gradient(linear,left top,left bottom,from(#ed6655),to(#e94b38)) repeat-x;background:#e94b38 -webkit-linear-gradient(top,#ed6655,#e94b38) repeat-x;background:#e94b38 -o-linear-gradient(top,#ed6655,#e94b38) repeat-x;background:#e94b38 linear-gradient(180deg,#ed6655,#e94b38) repeat-x;border-color:#e8402c}.btn-warning:focus,.btn-warning.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(237,106,90,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(237,106,90,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#fff;background-color:#ed6a5a;border-color:#ed6a5a}.btn-warning:not(:disabled):not(.disabled):active,.btn-warning:not(:disabled):not(.disabled).active,.show>.btn-warning.dropdown-toggle{color:#fff;background-color:#e8402c;background-image:none;border-color:#e73621}.btn-warning:not(:disabled):not(.disabled):active:focus,.btn-warning:not(:disabled):not(.disabled).active:focus,.show>.btn-warning.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5)}.btn-danger{color:#fff;background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x;border-color:#ed6a5a;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger:hover{color:#fff;background:#e94b38 -webkit-gradient(linear,left top,left bottom,from(#ed6655),to(#e94b38)) repeat-x;background:#e94b38 -webkit-linear-gradient(top,#ed6655,#e94b38) repeat-x;background:#e94b38 -o-linear-gradient(top,#ed6655,#e94b38) repeat-x;background:#e94b38 linear-gradient(180deg,#ed6655,#e94b38) repeat-x;border-color:#e8402c}.btn-danger:focus,.btn-danger.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(237,106,90,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(237,106,90,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#ed6a5a;border-color:#ed6a5a}.btn-danger:not(:disabled):not(.disabled):active,.btn-danger:not(:disabled):not(.disabled).active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#e8402c;background-image:none;border-color:#e73621}.btn-danger:not(:disabled):not(.disabled):active:focus,.btn-danger:not(:disabled):not(.disabled).active:focus,.show>.btn-danger.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5)}.btn-light{color:#222;background:#D3F3EE -webkit-gradient(linear,left top,left bottom,from(#daf5f1),to(#D3F3EE)) repeat-x;background:#d3f3ee -webkit-linear-gradient(top,#daf5f1,#D3F3EE) repeat-x;background:#d3f3ee -o-linear-gradient(top,#daf5f1,#D3F3EE) repeat-x;background:#d3f3ee linear-gradient(180deg,#daf5f1,#D3F3EE) repeat-x;border-color:#d3f3ee;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-light:hover{color:#222;background:#b5ebe2 -webkit-gradient(linear,left top,left bottom,from(#c0eee7),to(#b5ebe2)) repeat-x;background:#b5ebe2 -webkit-linear-gradient(top,#c0eee7,#b5ebe2) repeat-x;background:#b5ebe2 -o-linear-gradient(top,#c0eee7,#b5ebe2) repeat-x;background:#b5ebe2 linear-gradient(180deg,#c0eee7,#b5ebe2) repeat-x;border-color:#abe8df}.btn-light:focus,.btn-light.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(211,243,238,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(211,243,238,.5)}.btn-light.disabled,.btn-light:disabled{color:#222;background-color:#d3f3ee;border-color:#d3f3ee}.btn-light:not(:disabled):not(.disabled):active,.btn-light:not(:disabled):not(.disabled).active,.show>.btn-light.dropdown-toggle{color:#222;background-color:#abe8df;background-image:none;border-color:#a1e5db}.btn-light:not(:disabled):not(.disabled):active:focus,.btn-light:not(:disabled):not(.disabled).active:focus,.show>.btn-light.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(211,243,238,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(211,243,238,.5)}.btn-dark{color:#fff;background:#403F4C -webkit-gradient(linear,left top,left bottom,from(#5d5c67),to(#403F4C)) repeat-x;background:#403f4c -webkit-linear-gradient(top,#5d5c67,#403F4C) repeat-x;background:#403f4c -o-linear-gradient(top,#5d5c67,#403F4C) repeat-x;background:#403f4c linear-gradient(180deg,#5d5c67,#403F4C) repeat-x;border-color:#403f4c;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-dark:hover{color:#fff;background:#2e2e37 -webkit-gradient(linear,left top,left bottom,from(#4e4d55),to(#2e2e37)) repeat-x;background:#2e2e37 -webkit-linear-gradient(top,#4e4d55,#2e2e37) repeat-x;background:#2e2e37 -o-linear-gradient(top,#4e4d55,#2e2e37) repeat-x;background:#2e2e37 linear-gradient(180deg,#4e4d55,#2e2e37) repeat-x;border-color:#292830}.btn-dark:focus,.btn-dark.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(64,63,76,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(64,63,76,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#403f4c;border-color:#403f4c}.btn-dark:not(:disabled):not(.disabled):active,.btn-dark:not(:disabled):not(.disabled).active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#292830;background-image:none;border-color:#232229}.btn-dark:not(:disabled):not(.disabled):active:focus,.btn-dark:not(:disabled):not(.disabled).active:focus,.show>.btn-dark.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(64,63,76,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(64,63,76,.5)}.btn-outline-primary{color:#30638e;background-color:transparent;background-image:none;border-color:#30638e}.btn-outline-primary:hover{color:#fff;background-color:#30638e;border-color:#30638e}.btn-outline-primary:focus,.btn-outline-primary.focus{-webkit-box-shadow:0 0 0 .2rem rgba(48,99,142,.5);box-shadow:0 0 0 .2rem rgba(48,99,142,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#30638e;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled):active,.btn-outline-primary:not(:disabled):not(.disabled).active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#30638e;border-color:#30638e}.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(48,99,142,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(48,99,142,.5)}.btn-outline-secondary{color:#ffa630;background-color:transparent;background-image:none;border-color:#ffa630}.btn-outline-secondary:hover{color:#fff;background-color:#ffa630;border-color:#ffa630}.btn-outline-secondary:focus,.btn-outline-secondary.focus{-webkit-box-shadow:0 0 0 .2rem rgba(255,166,48,.5);box-shadow:0 0 0 .2rem rgba(255,166,48,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#ffa630;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled):active,.btn-outline-secondary:not(:disabled):not(.disabled).active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#ffa630;border-color:#ffa630}.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(255,166,48,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(255,166,48,.5)}.btn-outline-success{color:#3772ff;background-color:transparent;background-image:none;border-color:#3772ff}.btn-outline-success:hover{color:#fff;background-color:#3772ff;border-color:#3772ff}.btn-outline-success:focus,.btn-outline-success.focus{-webkit-box-shadow:0 0 0 .2rem rgba(55,114,255,.5);box-shadow:0 0 0 .2rem rgba(55,114,255,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#3772ff;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled):active,.btn-outline-success:not(:disabled):not(.disabled).active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#3772ff;border-color:#3772ff}.btn-outline-success:not(:disabled):not(.disabled):active:focus,.btn-outline-success:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-success.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(55,114,255,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(55,114,255,.5)}.btn-outline-info{color:#c0e0de;background-color:transparent;background-image:none;border-color:#c0e0de}.btn-outline-info:hover{color:#222;background-color:#c0e0de;border-color:#c0e0de}.btn-outline-info:focus,.btn-outline-info.focus{-webkit-box-shadow:0 0 0 .2rem rgba(192,224,222,.5);box-shadow:0 0 0 .2rem rgba(192,224,222,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#c0e0de;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled):active,.btn-outline-info:not(:disabled):not(.disabled).active,.show>.btn-outline-info.dropdown-toggle{color:#222;background-color:#c0e0de;border-color:#c0e0de}.btn-outline-info:not(:disabled):not(.disabled):active:focus,.btn-outline-info:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-info.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(192,224,222,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(192,224,222,.5)}.btn-outline-warning{color:#ed6a5a;background-color:transparent;background-image:none;border-color:#ed6a5a}.btn-outline-warning:hover{color:#fff;background-color:#ed6a5a;border-color:#ed6a5a}.btn-outline-warning:focus,.btn-outline-warning.focus{-webkit-box-shadow:0 0 0 .2rem rgba(237,106,90,.5);box-shadow:0 0 0 .2rem rgba(237,106,90,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ed6a5a;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled):active,.btn-outline-warning:not(:disabled):not(.disabled).active,.show>.btn-outline-warning.dropdown-toggle{color:#fff;background-color:#ed6a5a;border-color:#ed6a5a}.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5)}.btn-outline-danger{color:#ed6a5a;background-color:transparent;background-image:none;border-color:#ed6a5a}.btn-outline-danger:hover{color:#fff;background-color:#ed6a5a;border-color:#ed6a5a}.btn-outline-danger:focus,.btn-outline-danger.focus{-webkit-box-shadow:0 0 0 .2rem rgba(237,106,90,.5);box-shadow:0 0 0 .2rem rgba(237,106,90,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#ed6a5a;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled):active,.btn-outline-danger:not(:disabled):not(.disabled).active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#ed6a5a;border-color:#ed6a5a}.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5)}.btn-outline-light{color:#d3f3ee;background-color:transparent;background-image:none;border-color:#d3f3ee}.btn-outline-light:hover{color:#222;background-color:#d3f3ee;border-color:#d3f3ee}.btn-outline-light:focus,.btn-outline-light.focus{-webkit-box-shadow:0 0 0 .2rem rgba(211,243,238,.5);box-shadow:0 0 0 .2rem rgba(211,243,238,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#d3f3ee;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled):active,.btn-outline-light:not(:disabled):not(.disabled).active,.show>.btn-outline-light.dropdown-toggle{color:#222;background-color:#d3f3ee;border-color:#d3f3ee}.btn-outline-light:not(:disabled):not(.disabled):active:focus,.btn-outline-light:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-light.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(211,243,238,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(211,243,238,.5)}.btn-outline-dark{color:#403f4c;background-color:transparent;background-image:none;border-color:#403f4c}.btn-outline-dark:hover{color:#fff;background-color:#403f4c;border-color:#403f4c}.btn-outline-dark:focus,.btn-outline-dark.focus{-webkit-box-shadow:0 0 0 .2rem rgba(64,63,76,.5);box-shadow:0 0 0 .2rem rgba(64,63,76,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#403f4c;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled):active,.btn-outline-dark:not(:disabled):not(.disabled).active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#403f4c;border-color:#403f4c}.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(64,63,76,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(64,63,76,.5)}.btn-link{font-weight:400;color:#3176d9;background-color:transparent}.btn-link:hover{color:#1e53a0;text-decoration:none;background-color:transparent;border-color:transparent}.btn-link:focus,.btn-link.focus{text-decoration:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link:disabled,.btn-link.disabled{color:#888;pointer-events:none}.btn-lg,.btn-group-lg>.btn{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-sm,.btn-group-sm>.btn{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}@media screen and (prefers-reduced-motion:reduce){.fade{-webkit-transition:none;-o-transition:none;transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}@media screen and (prefers-reduced-motion:reduce){.collapsing{-webkit-transition:none;-o-transition:none;transition:none}}.dropup,.dropright,.dropdown,.dropleft{position:relative}.dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#222;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;-webkit-box-shadow:0 .5rem 1rem rgba(0,0,0,.175);box-shadow:0 .5rem 1rem rgba(0,0,0,.175)}.dropdown-menu-right{right:0;left:auto}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;width:0;height:0;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=top],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #eee}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#222;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:hover,.dropdown-item:focus{color:#151515;text-decoration:none;background:#f8f9fa -webkit-gradient(linear,left top,left bottom,from(#f9fafb),to(#f8f9fa)) repeat-x;background:#f8f9fa -webkit-linear-gradient(top,#f9fafb,#f8f9fa) repeat-x;background:#f8f9fa -o-linear-gradient(top,#f9fafb,#f8f9fa) repeat-x;background:#f8f9fa linear-gradient(180deg,#f9fafb,#f8f9fa) repeat-x}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x}.dropdown-item.disabled,.dropdown-item:disabled{color:#888;background-color:transparent;background-image:none}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#888;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#222}.btn-group,.btn-group-vertical{position:relative;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover{z-index:1}.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn.active{z-index:1}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group,.btn-group-vertical .btn+.btn,.btn-group-vertical .btn+.btn-group,.btn-group-vertical .btn-group+.btn,.btn-group-vertical .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:not(:last-child):not(.dropdown-toggle),.btn-group>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:not(:first-child),.btn-group>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-lg+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group.show .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.show .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn-group-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.btn-group-vertical .btn,.btn-group-vertical .btn-group{width:100%}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle),.btn-group-vertical>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.custom-select,.input-group>.custom-file{position:relative;-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;margin-bottom:0}.input-group>.form-control+.form-control,.input-group>.form-control+.custom-select,.input-group>.form-control+.custom-file,.input-group>.custom-select+.form-control,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.custom-file,.input-group>.custom-file+.form-control,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.custom-file{margin-left:-1px}.input-group>.form-control:focus,.input-group>.custom-select:focus,.input-group>.custom-file .custom-file-input:focus~.custom-file-label{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.form-control:not(:last-child),.input-group>.custom-select:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.form-control:not(:first-child),.input-group>.custom-select:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-prepend,.input-group-append{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.input-group-prepend .btn,.input-group-append .btn{position:relative;z-index:2}.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.input-group-text,.input-group-append .input-group-text+.btn{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#eee;border:1px solid #ccc;border-radius:.25rem}.input-group-text input[type=radio],.input-group-text input[type=checkbox]{margin-top:0}.input-group-lg>.form-control,.input-group-lg>.input-group-prepend>.input-group-text,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-append>.btn{height:-webkit-calc(2.875rem + 2px);height:calc(2.875rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.form-control,.input-group-sm>.input-group-prepend>.input-group-text,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-append>.btn{height:-webkit-calc(1.8125rem + 2px);height:calc(1.8125rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text,.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;z-index:-1;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x;-webkit-box-shadow:none;box-shadow:none}.custom-control-input:focus~.custom-control-label::before{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(48,99,142,.25);box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(48,99,142,.25)}.custom-control-input:active~.custom-control-label::before{color:#fff;background-color:#95bbdb;-webkit-box-shadow:none;box-shadow:none}.custom-control-input:disabled~.custom-control-label{color:#888}.custom-control-input:disabled~.custom-control-label::before{background-color:#eee}.custom-control-label{position:relative;margin-bottom:0}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#dee2e6;-webkit-box-shadow:inset 0 .25rem .25rem rgba(0,0,0,.1);box-shadow:inset 0 .25rem .25rem rgba(0,0,0,.1)}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background-repeat:no-repeat;background-position:50%;-webkit-background-size:50% 50%;background-size:50% 50%}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::before{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA4IDgiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik02LjU2NC43NWwtMy41OSAzLjYxMi0xLjUzOC0xLjU1TDAgNC4yNiAyLjk3NCA3LjI1IDggMi4xOTN6Ii8+PC9zdmc+)}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x;-webkit-box-shadow:none;box-shadow:none}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0IDQiPjxwYXRoIHN0cm9rZT0iI2ZmZiIgZD0iTTAgMmg0Ii8+PC9zdmc+)}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(48,99,142,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(48,99,142,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::before{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii00IC00IDggOCI+PGNpcmNsZSByPSIzIiBmaWxsPSIjZmZmIi8+PC9zdmc+)}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(48,99,142,.5)}.custom-select{display:inline-block;width:100%;height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px);padding:.375rem 1.75rem .375rem .75rem;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0IDUiPjxwYXRoIGZpbGw9IiMzMzMiIGQ9Ik0yIDAgMCAyaDR6bTAgNUwwIDNoNHoiLz48L3N2Zz4=) no-repeat 100% .75rem 50%;-webkit-background-size:8px 10px;background-size:8px 10px;border:1px solid #ccc;border-radius:.25rem;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.075);box-shadow:inset 0 1px 2px rgba(0,0,0,.075);-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#6fa3ce;outline:0;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.075),0 0 0 .2rem rgba(111,163,206,.5);box-shadow:inset 0 1px 2px rgba(0,0,0,.075),0 0 0 .2rem rgba(111,163,206,.5)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#888;background-color:#eee}.custom-select::-ms-expand{opacity:0}.custom-select-sm{height:-webkit-calc(1.8125rem + 2px);height:calc(1.8125rem + 2px);padding-top:.375rem;padding-bottom:.375rem;font-size:75%}.custom-select-lg{height:-webkit-calc(2.875rem + 2px);height:calc(2.875rem + 2px);padding-top:.375rem;padding-bottom:.375rem;font-size:125%}.custom-file{position:relative;display:inline-block;width:100%;height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px);margin:0;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#6fa3ce;-webkit-box-shadow:0 0 0 .2rem rgba(48,99,142,.25);box-shadow:0 0 0 .2rem rgba(48,99,142,.25)}.custom-file-input:focus~.custom-file-label::after{border-color:#6fa3ce}.custom-file-input:disabled~.custom-file-label{background-color:#eee}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px);padding:.375rem .75rem;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ccc;border-radius:.25rem;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:2.25rem;padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background:#eee -webkit-gradient(linear,left top,left bottom,from(#f1f1f1),to(#eee)) repeat-x;background:#eee -webkit-linear-gradient(top,#f1f1f1,#eee) repeat-x;background:#eee -o-linear-gradient(top,#f1f1f1,#eee) repeat-x;background:#eee linear-gradient(180deg,#f1f1f1,#eee) repeat-x;border-left:1px solid #ccc;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;padding-left:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:none}.custom-range:focus::-webkit-slider-thumb{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(48,99,142,.25);box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(48,99,142,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(48,99,142,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(48,99,142,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x;border:0;border-radius:1rem;-webkit-box-shadow:0 .1rem .25rem rgba(0,0,0,.1);box-shadow:0 .1rem .25rem rgba(0,0,0,.1);-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media screen and (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;-o-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background:#95bbdb -webkit-gradient(linear,left top,left bottom,from(#a5c5e1),to(#95bbdb)) repeat-x;background:#95bbdb -webkit-linear-gradient(top,#a5c5e1,#95bbdb) repeat-x;background:#95bbdb linear-gradient(180deg,#a5c5e1,#95bbdb) repeat-x}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem;-webkit-box-shadow:inset 0 .25rem .25rem rgba(0,0,0,.1);box-shadow:inset 0 .25rem .25rem rgba(0,0,0,.1)}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x;border:0;border-radius:1rem;box-shadow:0 .1rem .25rem rgba(0,0,0,.1);-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media screen and (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-webkit-transition:none;-o-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background:#95bbdb linear-gradient(180deg,#a5c5e1,#95bbdb) repeat-x}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem;box-shadow:inset 0 .25rem .25rem rgba(0,0,0,.1)}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x;border:0;border-radius:1rem;box-shadow:0 .1rem .25rem rgba(0,0,0,.1);-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;appearance:none}@media screen and (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-webkit-transition:none;-o-transition:none;transition:none}}.custom-range::-ms-thumb:active{background:#95bbdb linear-gradient(180deg,#a5c5e1,#95bbdb) repeat-x}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem;box-shadow:inset 0 .25rem .25rem rgba(0,0,0,.1)}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-control-label::before,.custom-file-label,.custom-select{-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media screen and (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{-webkit-transition:none;-o-transition:none;transition:none}}.nav{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:hover,.nav-link:focus{text-decoration:none}.nav-link.disabled{color:#888}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:hover,.nav-tabs .nav-link:focus{border-color:#eee #eee #dee2e6}.nav-tabs .nav-link.disabled{color:#888;background-color:transparent;border-color:transparent}.nav-tabs .nav-link.active,.nav-tabs .nav-item.show .nav-link{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#30638e}.nav-fill .nav-item{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar>.container,.navbar>.container-fluid{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-nav{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-webkit-flex-basis:100%;-ms-flex-preferred-size:100%;flex-basis:100%;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:hover,.navbar-toggler:focus{text-decoration:none}.navbar-toggler:not(:disabled):not(.disabled){cursor:pointer}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat 50%;-webkit-background-size:100% 100%;background-size:100% 100%}@media(max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{padding-right:0;padding-left:0}}@media(min-width:576px){.navbar-expand-sm{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media(max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{padding-right:0;padding-left:0}}@media(min-width:768px){.navbar-expand-md{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media(max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{padding-right:0;padding-left:0}}@media(min-width:992px){.navbar-expand-lg{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media(max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{padding-right:0;padding-left:0}}@media(min-width:1200px){.navbar-expand-xl{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:hover,.navbar-light .navbar-brand:focus{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:hover,.navbar-light .navbar-nav .nav-link:focus{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .show>.nav-link,.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .nav-link.active{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMzAgMzAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggc3Ryb2tlPSJyZ2JhKDAsIDAsIDAsIDAuNSkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIGQ9Ik00IDdoMjJNNCAxNWgyMk00IDIzaDIyIi8+PC9zdmc+)}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:hover,.navbar-light .navbar-text a:focus{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:hover,.navbar-dark .navbar-brand:focus{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link:hover,.navbar-dark .navbar-nav .nav-link:focus{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .show>.nav-link,.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .nav-link.active{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.75);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMzAgMzAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggc3Ryb2tlPSJyZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNzUpIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBkPSJNNCA3aDIyTTQgMTVoMjJNNCAyM2gyMiIvPjwvc3ZnPg==)}.navbar-dark .navbar-text{color:rgba(255,255,255,.75)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:hover,.navbar-dark .navbar-text a:focus{color:#fff}.card,.td-content .highlight{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr,.td-content .highlight>hr{margin-right:0;margin-left:0}.card>.list-group:first-child .list-group-item:first-child,.td-content .highlight>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child,.td-content .highlight>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-body{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:-webkit-calc(0.25rem - 1px) -webkit-calc(0.25rem - 1px) 0 0;border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 -webkit-calc(0.25rem - 1px) -webkit-calc(0.25rem - 1px);border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img{width:100%;border-radius:-webkit-calc(0.25rem - 1px);border-radius:calc(0.25rem - 1px)}.card-img-top{width:100%;border-top-left-radius:-webkit-calc(0.25rem - 1px);border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:-webkit-calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.card-img-bottom{width:100%;border-bottom-right-radius:-webkit-calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px);border-bottom-left-radius:-webkit-calc(0.25rem - 1px);border-bottom-left-radius:calc(0.25rem - 1px)}.card-deck{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.card-deck .card,.card-deck .td-content .highlight,.td-content .card-deck .highlight{margin-bottom:15px}@media(min-width:576px){.card-deck{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card,.card-deck .td-content .highlight,.td-content .card-deck .highlight{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1 0 0%;-ms-flex:1 0 0%;flex:1 0 0%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.card-group>.card,.td-content .card-group>.highlight{margin-bottom:15px}@media(min-width:576px){.card-group{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card,.td-content .card-group>.highlight{-webkit-box-flex:1;-webkit-flex:1 0 0%;-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card,.td-content .card-group>.highlight+.card,.td-content .card-group>.card+.highlight,.td-content .card-group>.highlight+.highlight{margin-left:0;border-left:0}.card-group>.card:first-child,.td-content .card-group>.highlight:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:first-child .card-img-top,.td-content .card-group>.highlight:first-child .card-img-top,.card-group>.card:first-child .card-header,.td-content .card-group>.highlight:first-child .card-header{border-top-right-radius:0}.card-group>.card:first-child .card-img-bottom,.td-content .card-group>.highlight:first-child .card-img-bottom,.card-group>.card:first-child .card-footer,.td-content .card-group>.highlight:first-child .card-footer{border-bottom-right-radius:0}.card-group>.card:last-child,.td-content .card-group>.highlight:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:last-child .card-img-top,.td-content .card-group>.highlight:last-child .card-img-top,.card-group>.card:last-child .card-header,.td-content .card-group>.highlight:last-child .card-header{border-top-left-radius:0}.card-group>.card:last-child .card-img-bottom,.td-content .card-group>.highlight:last-child .card-img-bottom,.card-group>.card:last-child .card-footer,.td-content .card-group>.highlight:last-child .card-footer{border-bottom-left-radius:0}.card-group>.card:only-child,.td-content .card-group>.highlight:only-child{border-radius:.25rem}.card-group>.card:only-child .card-img-top,.td-content .card-group>.highlight:only-child .card-img-top,.card-group>.card:only-child .card-header,.td-content .card-group>.highlight:only-child .card-header{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-group>.card:only-child .card-img-bottom,.td-content .card-group>.highlight:only-child .card-img-bottom,.card-group>.card:only-child .card-footer,.td-content .card-group>.highlight:only-child .card-footer{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-group>.card:not(:first-child):not(:last-child):not(:only-child),.td-content .card-group>.highlight:not(:first-child):not(:last-child):not(:only-child){border-radius:0}.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-img-top,.td-content .card-group>.highlight:not(:first-child):not(:last-child):not(:only-child) .card-img-top,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom,.td-content .card-group>.highlight:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-header,.td-content .card-group>.highlight:not(:first-child):not(:last-child):not(:only-child) .card-header,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-footer,.td-content .card-group>.highlight:not(:first-child):not(:last-child):not(:only-child) .card-footer{border-radius:0}}.card-columns .card,.card-columns .td-content .highlight,.td-content .card-columns .highlight{margin-bottom:.75rem}@media(min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card,.card-columns .td-content .highlight,.td-content .card-columns .highlight{display:inline-block;width:100%}}.accordion .card:not(:first-of-type):not(:last-of-type),.accordion .td-content .highlight:not(:first-of-type):not(:last-of-type),.td-content .accordion .highlight:not(:first-of-type):not(:last-of-type){border-bottom:0;border-radius:0}.accordion .card:not(:first-of-type) .card-header:first-child,.accordion .td-content .highlight:not(:first-of-type) .card-header:first-child,.td-content .accordion .highlight:not(:first-of-type) .card-header:first-child{border-radius:0}.accordion .card:first-of-type,.accordion .td-content .highlight:first-of-type,.td-content .accordion .highlight:first-of-type{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion .card:last-of-type,.accordion .td-content .highlight:last-of-type,.td-content .accordion .highlight:last-of-type{border-top-left-radius:0;border-top-right-radius:0}.breadcrumb{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#eee;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;color:#888;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#888}.pagination{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#888;background-color:#fff;border:1px solid rgba(0,0,0,.1)}.page-link:hover{z-index:2;color:#1e53a0;text-decoration:none;background-color:#eee;border-color:#dee2e6}.page-link:focus{z-index:2;outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(48,99,142,.25);box-shadow:0 0 0 .2rem rgba(48,99,142,.25)}.page-link:not(:disabled):not(.disabled){cursor:pointer}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:1;color:#fff;background-color:#30638e;border-color:#2a567b}.page-item.disabled .page-link{color:#dee2e6;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#30638e}.badge-primary[href]:hover,.badge-primary[href]:focus{color:#fff;text-decoration:none;background-color:#234868}.badge-secondary{color:#fff;background-color:#ffa630}.badge-secondary[href]:hover,.badge-secondary[href]:focus{color:#fff;text-decoration:none;background-color:#fc9000}.badge-success{color:#fff;background-color:#3772ff}.badge-success[href]:hover,.badge-success[href]:focus{color:#fff;text-decoration:none;background-color:#044eff}.badge-info{color:#222;background-color:#c0e0de}.badge-info[href]:hover,.badge-info[href]:focus{color:#222;text-decoration:none;background-color:#9ecfcc}.badge-warning{color:#fff;background-color:#ed6a5a}.badge-warning[href]:hover,.badge-warning[href]:focus{color:#fff;text-decoration:none;background-color:#e8402c}.badge-danger{color:#fff;background-color:#ed6a5a}.badge-danger[href]:hover,.badge-danger[href]:focus{color:#fff;text-decoration:none;background-color:#e8402c}.badge-light{color:#222;background-color:#d3f3ee}.badge-light[href]:hover,.badge-light[href]:focus{color:#222;text-decoration:none;background-color:#abe8df}.badge-dark{color:#fff;background-color:#403f4c}.badge-dark[href]:hover,.badge-dark[href]:focus{color:#fff;text-decoration:none;background-color:#292830}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#eee;border-radius:.3rem}@media(min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#19334a;background:#d6e0e8 -webkit-gradient(linear,left top,left bottom,from(#dce5eb),to(#d6e0e8)) repeat-x;background:#d6e0e8 -webkit-linear-gradient(top,#dce5eb,#d6e0e8) repeat-x;background:#d6e0e8 -o-linear-gradient(top,#dce5eb,#d6e0e8) repeat-x;background:#d6e0e8 linear-gradient(180deg,#dce5eb,#d6e0e8) repeat-x;border-color:#c5d3df}.alert-primary hr{border-top-color:#b5c7d6}.alert-primary .alert-link{color:#0c1924}.alert-secondary{color:#855619;background:#ffedd6 -webkit-gradient(linear,left top,left bottom,from(#fff0dc),to(#ffedd6)) repeat-x;background:#ffedd6 -webkit-linear-gradient(top,#fff0dc,#ffedd6) repeat-x;background:#ffedd6 -o-linear-gradient(top,#fff0dc,#ffedd6) repeat-x;background:#ffedd6 linear-gradient(180deg,#fff0dc,#ffedd6) repeat-x;border-color:#ffe6c5}.alert-secondary hr{border-top-color:#ffdbac}.alert-secondary .alert-link{color:#5a3a11}.alert-success{color:#1d3b85;background:#d7e3ff -webkit-gradient(linear,left top,left bottom,from(#dde7ff),to(#d7e3ff)) repeat-x;background:#d7e3ff -webkit-linear-gradient(top,#dde7ff,#d7e3ff) repeat-x;background:#d7e3ff -o-linear-gradient(top,#dde7ff,#d7e3ff) repeat-x;background:#d7e3ff linear-gradient(180deg,#dde7ff,#d7e3ff) repeat-x;border-color:#c7d8ff}.alert-success hr{border-top-color:#aec6ff}.alert-success .alert-link{color:#14285b}.alert-info{color:#647473;background:#f2f9f8 -webkit-gradient(linear,left top,left bottom,from(#f4faf9),to(#f2f9f8)) repeat-x;background:#f2f9f8 -webkit-linear-gradient(top,#f4faf9,#f2f9f8) repeat-x;background:#f2f9f8 -o-linear-gradient(top,#f4faf9,#f2f9f8) repeat-x;background:#f2f9f8 linear-gradient(180deg,#f4faf9,#f2f9f8) repeat-x;border-color:#edf6f6}.alert-info hr{border-top-color:#dceeee}.alert-info .alert-link{color:#4c5958}.alert-warning{color:#7b372f;background:#fbe1de -webkit-gradient(linear,left top,left bottom,from(#fce6e3),to(#fbe1de)) repeat-x;background:#fbe1de -webkit-linear-gradient(top,#fce6e3,#fbe1de) repeat-x;background:#fbe1de -o-linear-gradient(top,#fce6e3,#fbe1de) repeat-x;background:#fbe1de linear-gradient(180deg,#fce6e3,#fbe1de) repeat-x;border-color:#fad5d1}.alert-warning hr{border-top-color:#f8c0ba}.alert-warning .alert-link{color:#562721}.alert-danger{color:#7b372f;background:#fbe1de -webkit-gradient(linear,left top,left bottom,from(#fce6e3),to(#fbe1de)) repeat-x;background:#fbe1de -webkit-linear-gradient(top,#fce6e3,#fbe1de) repeat-x;background:#fbe1de -o-linear-gradient(top,#fce6e3,#fbe1de) repeat-x;background:#fbe1de linear-gradient(180deg,#fce6e3,#fbe1de) repeat-x;border-color:#fad5d1}.alert-danger hr{border-top-color:#f8c0ba}.alert-danger .alert-link{color:#562721}.alert-light{color:#6e7e7c;background:#f6fdfc -webkit-gradient(linear,left top,left bottom,from(#f7fdfc),to(#f6fdfc)) repeat-x;background:#f6fdfc -webkit-linear-gradient(top,#f7fdfc,#f6fdfc) repeat-x;background:#f6fdfc -o-linear-gradient(top,#f7fdfc,#f6fdfc) repeat-x;background:#f6fdfc linear-gradient(180deg,#f7fdfc,#f6fdfc) repeat-x;border-color:#f3fcfa}.alert-light hr{border-top-color:#dff7f2}.alert-light .alert-link{color:#566361}.alert-dark{color:#212128;background:#d9d9db -webkit-gradient(linear,left top,left bottom,from(#dfdfe0),to(#d9d9db)) repeat-x;background:#d9d9db -webkit-linear-gradient(top,#dfdfe0,#d9d9db) repeat-x;background:#d9d9db -o-linear-gradient(top,#dfdfe0,#d9d9db) repeat-x;background:#d9d9db linear-gradient(180deg,#dfdfe0,#d9d9db) repeat-x;border-color:#cac9cd}.alert-dark hr{border-top-color:#bdbcc1}.alert-dark .alert-link{color:#0a0a0c}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#eee;border-radius:.25rem;-webkit-box-shadow:inset 0 .1rem .1rem rgba(0,0,0,.1);box-shadow:inset 0 .1rem .1rem rgba(0,0,0,.1)}.progress-bar{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;color:#fff;text-align:center;white-space:nowrap;background-color:#30638e;-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}@media screen and (prefers-reduced-motion:reduce){.progress-bar{-webkit-transition:none;-o-transition:none;transition:none}}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:1rem 1rem;background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;-o-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}.media{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start}.media-body{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.list-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:hover,.list-group-item-action:focus{color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#222;background-color:#eee}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;margin-bottom:-1px;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item:hover,.list-group-item:focus{z-index:1;text-decoration:none}.list-group-item.disabled,.list-group-item:disabled{color:#888;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#30638e;border-color:#30638e}.list-group-flush .list-group-item{border-right:0;border-left:0;border-radius:0}.list-group-flush:first-child .list-group-item:first-child{border-top:0}.list-group-flush:last-child .list-group-item:last-child{border-bottom:0}.list-group-item-primary{color:#19334a;background-color:#c5d3df}.list-group-item-primary.list-group-item-action:hover,.list-group-item-primary.list-group-item-action:focus{color:#19334a;background-color:#b5c7d6}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#19334a;border-color:#19334a}.list-group-item-secondary{color:#855619;background-color:#ffe6c5}.list-group-item-secondary.list-group-item-action:hover,.list-group-item-secondary.list-group-item-action:focus{color:#855619;background-color:#ffdbac}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#855619;border-color:#855619}.list-group-item-success{color:#1d3b85;background-color:#c7d8ff}.list-group-item-success.list-group-item-action:hover,.list-group-item-success.list-group-item-action:focus{color:#1d3b85;background-color:#aec6ff}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#1d3b85;border-color:#1d3b85}.list-group-item-info{color:#647473;background-color:#edf6f6}.list-group-item-info.list-group-item-action:hover,.list-group-item-info.list-group-item-action:focus{color:#647473;background-color:#dceeee}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#647473;border-color:#647473}.list-group-item-warning{color:#7b372f;background-color:#fad5d1}.list-group-item-warning.list-group-item-action:hover,.list-group-item-warning.list-group-item-action:focus{color:#7b372f;background-color:#f8c0ba}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#7b372f;border-color:#7b372f}.list-group-item-danger{color:#7b372f;background-color:#fad5d1}.list-group-item-danger.list-group-item-action:hover,.list-group-item-danger.list-group-item-action:focus{color:#7b372f;background-color:#f8c0ba}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#7b372f;border-color:#7b372f}.list-group-item-light{color:#6e7e7c;background-color:#f3fcfa}.list-group-item-light.list-group-item-action:hover,.list-group-item-light.list-group-item-action:focus{color:#6e7e7c;background-color:#dff7f2}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#6e7e7c;border-color:#6e7e7c}.list-group-item-dark{color:#212128;background-color:#cac9cd}.list-group-item-dark.list-group-item-action:hover,.list-group-item-dark.list-group-item-action:focus{color:#212128;background-color:#bdbcc1}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#212128;border-color:#212128}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:not(:disabled):not(.disabled){cursor:pointer}.close:not(:disabled):not(.disabled):hover,.close:not(:disabled):not(.disabled):focus{color:#000;text-decoration:none;opacity:.75}button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out,-o-transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}@media screen and (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{-webkit-transition:none;-o-transition:none;transition:none}}.modal.show .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-dialog-centered{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;min-height:-webkit-calc(100% - (0.5rem * 2));min-height:calc(100% - (0.5rem * 2))}.modal-dialog-centered::before{display:block;height:-webkit-calc(100vh - (0.5rem * 2));height:calc(100vh - (0.5rem * 2));content:""}.modal-content{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;-webkit-box-shadow:0 .25rem .5rem rgba(0,0,0,.5);box-shadow:0 .25rem .5rem rgba(0,0,0,.5);outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;padding:1rem;border-bottom:1px solid #eee;border-top-left-radius:.3rem;border-top-right-radius:.3rem}.modal-header .close{padding:1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;padding:1rem;border-top:1px solid #eee}.modal-footer>:not(:first-child){margin-left:.25rem}.modal-footer>:not(:last-child){margin-right:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media(min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-centered{min-height:-webkit-calc(100% - (1.75rem * 2));min-height:calc(100% - (1.75rem * 2))}.modal-dialog-centered::before{height:-webkit-calc(100vh - (1.75rem * 2));height:calc(100vh - (1.75rem * 2))}.modal-content{-webkit-box-shadow:0 .5rem 1rem rgba(0,0,0,.5);box-shadow:0 .5rem 1rem rgba(0,0,0,.5)}.modal-sm{max-width:300px}}@media(min-width:992px){.modal-lg{max-width:800px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:open sans,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-top,.bs-tooltip-auto[x-placement^=top]{padding:.4rem 0}.bs-tooltip-top .arrow,.bs-tooltip-auto[x-placement^=top] .arrow{bottom:0}.bs-tooltip-top .arrow::before,.bs-tooltip-auto[x-placement^=top] .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-right,.bs-tooltip-auto[x-placement^=right]{padding:0 .4rem}.bs-tooltip-right .arrow,.bs-tooltip-auto[x-placement^=right] .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-right .arrow::before,.bs-tooltip-auto[x-placement^=right] .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-bottom,.bs-tooltip-auto[x-placement^=bottom]{padding:.4rem 0}.bs-tooltip-bottom .arrow,.bs-tooltip-auto[x-placement^=bottom] .arrow{top:0}.bs-tooltip-bottom .arrow::before,.bs-tooltip-auto[x-placement^=bottom] .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-left,.bs-tooltip-auto[x-placement^=left]{padding:0 .4rem}.bs-tooltip-left .arrow,.bs-tooltip-auto[x-placement^=left] .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-left .arrow::before,.bs-tooltip-auto[x-placement^=left] .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:open sans,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;-webkit-box-shadow:0 .25rem .5rem rgba(0,0,0,.2);box-shadow:0 .25rem .5rem rgba(0,0,0,.2)}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::before,.popover .arrow::after{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-top,.bs-popover-auto[x-placement^=top]{margin-bottom:.5rem}.bs-popover-top .arrow,.bs-popover-auto[x-placement^=top] .arrow{bottom:-webkit-calc((0.5rem + 1px) * -1);bottom:calc((0.5rem + 1px) * -1)}.bs-popover-top .arrow::before,.bs-popover-auto[x-placement^=top] .arrow::before,.bs-popover-top .arrow::after,.bs-popover-auto[x-placement^=top] .arrow::after{border-width:.5rem .5rem 0}.bs-popover-top .arrow::before,.bs-popover-auto[x-placement^=top] .arrow::before{bottom:0;border-top-color:rgba(0,0,0,.25)}.bs-popover-top .arrow::after,.bs-popover-auto[x-placement^=top] .arrow::after{bottom:1px;border-top-color:#fff}.bs-popover-right,.bs-popover-auto[x-placement^=right]{margin-left:.5rem}.bs-popover-right .arrow,.bs-popover-auto[x-placement^=right] .arrow{left:-webkit-calc((0.5rem + 1px) * -1);left:calc((0.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-right .arrow::before,.bs-popover-auto[x-placement^=right] .arrow::before,.bs-popover-right .arrow::after,.bs-popover-auto[x-placement^=right] .arrow::after{border-width:.5rem .5rem .5rem 0}.bs-popover-right .arrow::before,.bs-popover-auto[x-placement^=right] .arrow::before{left:0;border-right-color:rgba(0,0,0,.25)}.bs-popover-right .arrow::after,.bs-popover-auto[x-placement^=right] .arrow::after{left:1px;border-right-color:#fff}.bs-popover-bottom,.bs-popover-auto[x-placement^=bottom]{margin-top:.5rem}.bs-popover-bottom .arrow,.bs-popover-auto[x-placement^=bottom] .arrow{top:-webkit-calc((0.5rem + 1px) * -1);top:calc((0.5rem + 1px) * -1)}.bs-popover-bottom .arrow::before,.bs-popover-auto[x-placement^=bottom] .arrow::before,.bs-popover-bottom .arrow::after,.bs-popover-auto[x-placement^=bottom] .arrow::after{border-width:0 .5rem .5rem}.bs-popover-bottom .arrow::before,.bs-popover-auto[x-placement^=bottom] .arrow::before{top:0;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-bottom .arrow::after,.bs-popover-auto[x-placement^=bottom] .arrow::after{top:1px;border-bottom-color:#fff}.bs-popover-bottom .popover-header::before,.bs-popover-auto[x-placement^=bottom] .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-left,.bs-popover-auto[x-placement^=left]{margin-right:.5rem}.bs-popover-left .arrow,.bs-popover-auto[x-placement^=left] .arrow{right:-webkit-calc((0.5rem + 1px) * -1);right:calc((0.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-left .arrow::before,.bs-popover-auto[x-placement^=left] .arrow::before,.bs-popover-left .arrow::after,.bs-popover-auto[x-placement^=left] .arrow::after{border-width:.5rem 0 .5rem .5rem}.bs-popover-left .arrow::before,.bs-popover-auto[x-placement^=left] .arrow::before{right:0;border-left-color:rgba(0,0,0,.25)}.bs-popover-left .arrow::after,.bs-popover-auto[x-placement^=left] .arrow::after{right:1px;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;color:inherit;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:-webkit-calc(0.3rem - 1px);border-top-left-radius:calc(0.3rem - 1px);border-top-right-radius:-webkit-calc(0.3rem - 1px);border-top-right-radius:calc(0.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#222}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-item{position:relative;display:none;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;width:100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-item.active,.carousel-item-next,.carousel-item-prev{display:block;-webkit-transition:-webkit-transform .6s ease;transition:-webkit-transform .6s ease;-o-transition:-o-transform .6s ease;transition:transform .6s ease;transition:transform .6s ease,-webkit-transform .6s ease,-o-transform .6s ease}@media screen and (prefers-reduced-motion:reduce){.carousel-item.active,.carousel-item-next,.carousel-item-prev{-webkit-transition:none;-o-transition:none;transition:none}}.carousel-item-next,.carousel-item-prev{position:absolute;top:0}.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translateX(0);-ms-transform:translateX(0);-o-transform:translateX(0);transform:translateX(0)}@supports((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-item-next,.active.carousel-item-right{-webkit-transform:translateX(100%);-ms-transform:translateX(100%);-o-transform:translateX(100%);transform:translateX(100%)}@supports((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-item-next,.active.carousel-item-right{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.carousel-item-prev,.active.carousel-item-left{-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);-o-transform:translateX(-100%);transform:translateX(-100%)}@supports((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-item-prev,.active.carousel-item-left{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.carousel-fade .carousel-item{opacity:0;-webkit-transition-duration:.6s;-o-transition-duration:.6s;transition-duration:.6s;-webkit-transition-property:opacity;-o-transition-property:opacity;transition-property:opacity}.carousel-fade .carousel-item.active,.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right{opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{opacity:0}.carousel-fade .carousel-item-next,.carousel-fade .carousel-item-prev,.carousel-fade .carousel-item.active,.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-prev{-webkit-transform:translateX(0);-ms-transform:translateX(0);-o-transform:translateX(0);transform:translateX(0)}@supports((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-fade .carousel-item-next,.carousel-fade .carousel-item-prev,.carousel-fade .carousel-item.active,.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-prev{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-control-prev,.carousel-control-next{position:absolute;top:0;bottom:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0;background:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,0.25)),to(rgba(0,0,0,0.001)));background:-webkit-linear-gradient(left,rgba(0,0,0,0.25),rgba(0,0,0,0.001));background:-o-linear-gradient(left,rgba(0,0,0,0.25),rgba(0,0,0,0.001));background:linear-gradient(90deg,rgba(0,0,0,0.25),rgba(0,0,0,0.001))}.carousel-control-next{right:0;background:-webkit-gradient(linear,right top,left top,from(rgba(0,0,0,0.25)),to(rgba(0,0,0,0.001)));background:-webkit-linear-gradient(right,rgba(0,0,0,0.25),rgba(0,0,0,0.001));background:-o-linear-gradient(right,rgba(0,0,0,0.25),rgba(0,0,0,0.001));background:linear-gradient(270deg,rgba(0,0,0,0.25),rgba(0,0,0,0.001))}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:20px;height:20px;background:transparent no-repeat 50%;-webkit-background-size:100% 100%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiNmZmYiIHZpZXdCb3g9IjAgMCA4IDgiPjxwYXRoIGQ9Ik01LjI1LjBsLTQgNCA0IDQgMS41LTEuNUw0LjI1IDRsMi41LTIuNUw1LjI1LjB6Ii8+PC9zdmc+)}.carousel-control-next-icon{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiNmZmYiIHZpZXdCb3g9IjAgMCA4IDgiPjxwYXRoIGQ9Ik0yLjc1LjBsLTEuNSAxLjVMMy43NSA0bC0yLjUgMi41TDIuNzUgOGw0LTQtNC00eiIvPjwvc3ZnPg==)}.carousel-indicators{position:absolute;right:0;bottom:10px;left:0;z-index:15;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{position:relative;-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:rgba(255,255,255,.5)}.carousel-indicators li::before{position:absolute;top:-10px;left:0;display:inline-block;width:100%;height:10px;content:""}.carousel-indicators li::after{position:absolute;bottom:-10px;left:0;display:inline-block;width:100%;height:10px;content:""}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#30638e!important}a.bg-primary:hover,a.bg-primary:focus,button.bg-primary:hover,button.bg-primary:focus{background-color:#234868!important}.bg-secondary{background-color:#ffa630!important}a.bg-secondary:hover,a.bg-secondary:focus,button.bg-secondary:hover,button.bg-secondary:focus{background-color:#fc9000!important}.bg-success{background-color:#3772ff!important}a.bg-success:hover,a.bg-success:focus,button.bg-success:hover,button.bg-success:focus{background-color:#044eff!important}.bg-info{background-color:#c0e0de!important}a.bg-info:hover,a.bg-info:focus,button.bg-info:hover,button.bg-info:focus{background-color:#9ecfcc!important}.bg-warning{background-color:#ed6a5a!important}a.bg-warning:hover,a.bg-warning:focus,button.bg-warning:hover,button.bg-warning:focus{background-color:#e8402c!important}.bg-danger{background-color:#ed6a5a!important}a.bg-danger:hover,a.bg-danger:focus,button.bg-danger:hover,button.bg-danger:focus{background-color:#e8402c!important}.bg-light{background-color:#d3f3ee!important}a.bg-light:hover,a.bg-light:focus,button.bg-light:hover,button.bg-light:focus{background-color:#abe8df!important}.bg-dark{background-color:#403f4c!important}a.bg-dark:hover,a.bg-dark:focus,button.bg-dark:hover,button.bg-dark:focus{background-color:#292830!important}.bg-gradient-primary{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x!important;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x!important}.bg-gradient-secondary{background:#FFA630 -webkit-gradient(linear,left top,left bottom,from(#ffb34f),to(#FFA630)) repeat-x!important;background:#ffa630 -webkit-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 -o-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 linear-gradient(180deg,#ffb34f,#FFA630) repeat-x!important}.bg-gradient-success{background:#3772FF -webkit-gradient(linear,left top,left bottom,from(#5587ff),to(#3772FF)) repeat-x!important;background:#3772ff -webkit-linear-gradient(top,#5587ff,#3772FF) repeat-x!important;background:#3772ff -o-linear-gradient(top,#5587ff,#3772FF) repeat-x!important;background:#3772ff linear-gradient(180deg,#5587ff,#3772FF) repeat-x!important}.bg-gradient-info{background:#C0E0DE -webkit-gradient(linear,left top,left bottom,from(#c9e5e3),to(#C0E0DE)) repeat-x!important;background:#c0e0de -webkit-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de -o-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de linear-gradient(180deg,#c9e5e3,#C0E0DE) repeat-x!important}.bg-gradient-warning{background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x!important;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x!important}.bg-gradient-danger{background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x!important;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x!important}.bg-gradient-light{background:#D3F3EE -webkit-gradient(linear,left top,left bottom,from(#daf5f1),to(#D3F3EE)) repeat-x!important;background:#d3f3ee -webkit-linear-gradient(top,#daf5f1,#D3F3EE) repeat-x!important;background:#d3f3ee -o-linear-gradient(top,#daf5f1,#D3F3EE) repeat-x!important;background:#d3f3ee linear-gradient(180deg,#daf5f1,#D3F3EE) repeat-x!important}.bg-gradient-dark{background:#403F4C -webkit-gradient(linear,left top,left bottom,from(#5d5c67),to(#403F4C)) repeat-x!important;background:#403f4c -webkit-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c -o-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c linear-gradient(180deg,#5d5c67,#403F4C) repeat-x!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#30638e!important}.border-secondary{border-color:#ffa630!important}.border-success{border-color:#3772ff!important}.border-info{border-color:#c0e0de!important}.border-warning{border-color:#ed6a5a!important}.border-danger{border-color:#ed6a5a!important}.border-light{border-color:#d3f3ee!important}.border-dark{border-color:#403f4c!important}.border-white{border-color:#fff!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-circle{border-radius:50%!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}@media(min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media(min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media(min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media(min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.85714286%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}@media(min-width:576px){.flex-sm-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media(min-width:768px){.flex-md-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media(min-width:992px){.flex-lg-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media(min-width:1200px){.flex-xl-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media(min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media(min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media(min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media(min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{-webkit-box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important;box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{-webkit-box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important;box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{-webkit-box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important;box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{-webkit-box-shadow:none!important;box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media(min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media(min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media(min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media(min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,liberation mono,courier new,monospace}.text-justify{text-align:justify!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media(min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media(min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media(min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media(min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#30638e!important}a.text-primary:hover,a.text-primary:focus{color:#234868!important}.text-secondary{color:#ffa630!important}a.text-secondary:hover,a.text-secondary:focus{color:#fc9000!important}.text-success{color:#3772ff!important}a.text-success:hover,a.text-success:focus{color:#044eff!important}.text-info{color:#c0e0de!important}a.text-info:hover,a.text-info:focus{color:#9ecfcc!important}.text-warning{color:#ed6a5a!important}a.text-warning:hover,a.text-warning:focus{color:#e8402c!important}.text-danger{color:#ed6a5a!important}a.text-danger:hover,a.text-danger:focus{color:#e8402c!important}.text-light{color:#d3f3ee!important}a.text-light:hover,a.text-light:focus{color:#abe8df!important}.text-dark{color:#403f4c!important}a.text-dark:hover,a.text-dark:focus{color:#292830!important}.text-body{color:#222!important}.text-muted{color:#888!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,*::before,*::after{text-shadow:none!important;-webkit-box-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}pre,blockquote{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table,.td-box .row.section>table,.td-content>table{border-collapse:collapse!important}.table td,.td-box .row.section>table td,.td-content>table td,.table th,.td-box .row.section>table th,.td-content>table th{background-color:#fff!important}.table-bordered th,.table-bordered td{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark th,.table-dark td,.table-dark thead th,.table-dark tbody+tbody{border-color:#dee2e6}.table .thead-dark th,.td-box .row.section>table .thead-dark th,.td-content>table .thead-dark th{color:inherit;border-color:#dee2e6}}/*!* Font Awesome Free 5.10.1 by @fontawesome - https://fontawesome.com +* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)*/.fa,.fas,.far,.fal,.fad,.fab{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:solid .08em #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fas.fa-pull-left,.far.fa-pull-left,.fal.fa-pull-left,.fab.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fas.fa-pull-right,.far.fa-pull-right,.fal.fa-pull-right,.fab.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;-o-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);-o-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-o-keyframes fa-spin{0%{-o-transform:rotate(0deg);transform:rotate(0deg)}100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);-o-transform:rotate(360deg);transform:rotate(360deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);-o-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(-1,-1);-ms-transform:scale(-1,-1);-o-transform:scale(-1,-1);transform:scale(-1,-1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-flip-both{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adobe:before{content:"\f778"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-atlassian:before{content:"\f77b"}.fa-atom:before{content:"\f5d2"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-baby:before{content:"\f77c"}.fa-baby-carriage:before{content:"\f77d"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-bacon:before{content:"\f7e5"}.fa-balance-scale:before{content:"\f24e"}.fa-balance-scale-left:before{content:"\f515"}.fa-balance-scale-right:before{content:"\f516"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-battle-net:before{content:"\f835"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bible:before{content:"\f647"}.fa-bicycle:before{content:"\f206"}.fa-biking:before{content:"\f84a"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-biohazard:before{content:"\f780"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blind:before{content:"\f29d"}.fa-blog:before{content:"\f781"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-dead:before{content:"\f6b7"}.fa-book-medical:before{content:"\f7e6"}.fa-book-open:before{content:"\f518"}.fa-book-reader:before{content:"\f5da"}.fa-bookmark:before{content:"\f02e"}.fa-bootstrap:before{content:"\f836"}.fa-border-all:before{content:"\f84c"}.fa-border-none:before{content:"\f850"}.fa-border-style:before{content:"\f853"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-bread-slice:before{content:"\f7ec"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-buffer:before{content:"\f837"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-business-time:before{content:"\f64a"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-day:before{content:"\f783"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-calendar-week:before{content:"\f784"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-campground:before{content:"\f6bb"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-candy-cane:before{content:"\f786"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-car-alt:before{content:"\f5de"}.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-side:before{content:"\f5e4"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-carrot:before{content:"\f787"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cash-register:before{content:"\f788"}.fa-cat:before{content:"\f6be"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-centos:before{content:"\f789"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-charging-station:before{content:"\f5e7"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-cheese:before{content:"\f7ef"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-chromecast:before{content:"\f838"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-city:before{content:"\f64f"}.fa-clinic-medical:before{content:"\f7f2"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-medical:before{content:"\f7f5"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-compress-arrows-alt:before{content:"\f78c"}.fa-concierge-bell:before{content:"\f562"}.fa-confluence:before{content:"\f78d"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-cotton-bureau:before{content:"\f89e"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-credit-card:before{content:"\f09d"}.fa-critical-role:before{content:"\f6c9"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-crutch:before{content:"\f7f7"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-delicious:before{content:"\f1a5"}.fa-democrat:before{content:"\f747"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dharmachakra:before{content:"\f655"}.fa-dhl:before{content:"\f790"}.fa-diagnoses:before{content:"\f470"}.fa-diaspora:before{content:"\f791"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-directions:before{content:"\f5eb"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dumpster:before{content:"\f793"}.fa-dumpster-fire:before{content:"\f794"}.fa-dungeon:before{content:"\f6d9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edit:before{content:"\f044"}.fa-egg:before{content:"\f7fb"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-ethernet:before{content:"\f796"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-evernote:before{content:"\f839"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fan:before{content:"\f863"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-fedex:before{content:"\f797"}.fa-fedora:before{content:"\f798"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-figma:before{content:"\f799"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-alt:before{content:"\f7e4"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-fist-raised:before{content:"\f6de"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-funnel-dollar:before{content:"\f662"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-gifts:before{content:"\f79c"}.fa-git:before{content:"\f1d3"}.fa-git-alt:before{content:"\f841"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-cheers:before{content:"\f79f"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glass-whiskey:before{content:"\f7a0"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-globe-europe:before{content:"\f7a2"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-lines:before{content:"\f7a4"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-guitar:before{content:"\f7a6"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hamburger:before{content:"\f805"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-middle-finger:before{content:"\f806"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-handshake:before{content:"\f2b5"}.fa-hanukiah:before{content:"\f6e6"}.fa-hard-hat:before{content:"\f807"}.fa-hashtag:before{content:"\f292"}.fa-hat-wizard:before{content:"\f6e8"}.fa-haykal:before{content:"\f666"}.fa-hdd:before{content:"\f0a0"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heart-broken:before{content:"\f7a9"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hiking:before{content:"\f6ec"}.fa-hippo:before{content:"\f6ed"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hockey-puck:before{content:"\f453"}.fa-holly-berry:before{content:"\f7aa"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-horse:before{content:"\f6f0"}.fa-horse-head:before{content:"\f7ab"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hot-tub:before{content:"\f593"}.fa-hotdog:before{content:"\f80f"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-house-damage:before{content:"\f6f1"}.fa-houzz:before{content:"\f27c"}.fa-hryvnia:before{content:"\f6f2"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-ice-cream:before{content:"\f810"}.fa-icicles:before{content:"\f7ad"}.fa-icons:before{content:"\f86d"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-igloo:before{content:"\f7ae"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-instagram:before{content:"\f16d"}.fa-intercom:before{content:"\f7af"}.fa-internet-explorer:before{content:"\f26b"}.fa-invision:before{content:"\f7b0"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itch-io:before{content:"\f83a"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi:before{content:"\f669"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-jira:before{content:"\f7b1"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-journal-whills:before{content:"\f66a"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaaba:before{content:"\f66b"}.fa-kaggle:before{content:"\f5fa"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-khanda:before{content:"\f66d"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laptop-medical:before{content:"\f812"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mail-bulk:before{content:"\f674"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-markdown:before{content:"\f60f"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mask:before{content:"\f6fa"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-mendeley:before{content:"\f7b3"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-meteor:before{content:"\f753"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mitten:before{content:"\f7b5"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mouse-pointer:before{content:"\f245"}.fa-mug-hot:before{content:"\f7b6"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-oil-can:before{content:"\f613"}.fa-old-republic:before{content:"\f510"}.fa-om:before{content:"\f679"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-osi:before{content:"\f41a"}.fa-otter:before{content:"\f700"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-pager:before{content:"\f815"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-pastafarianism:before{content:"\f67b"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-penny-arcade:before{content:"\f704"}.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-person-booth:before{content:"\f756"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-alt:before{content:"\f879"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-square-alt:before{content:"\f87b"}.fa-phone-volume:before{content:"\f2a0"}.fa-photo-video:before{content:"\f87c"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-pizza-slice:before{content:"\f818"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poll:before{content:"\f681"}.fa-poll-h:before{content:"\f682"}.fa-poo:before{content:"\f2fe"}.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-pray:before{content:"\f683"}.fa-praying-hands:before{content:"\f684"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-quran:before{content:"\f687"}.fa-r-project:before{content:"\f4f7"}.fa-radiation:before{content:"\f7b9"}.fa-radiation-alt:before{content:"\f7ba"}.fa-rainbow:before{content:"\f75b"}.fa-random:before{content:"\f074"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redhat:before{content:"\f7bc"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-remove-format:before{content:"\f87d"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-republican:before{content:"\f75e"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-restroom:before{content:"\f7bd"}.fa-retweet:before{content:"\f079"}.fa-rev:before{content:"\f5b2"}.fa-ribbon:before{content:"\f4d6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-route:before{content:"\f4d7"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-running:before{content:"\f70c"}.fa-rupee-sign:before{content:"\f156"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-salesforce:before{content:"\f83b"}.fa-sass:before{content:"\f41e"}.fa-satellite:before{content:"\f7bf"}.fa-satellite-dish:before{content:"\f7c0"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-scroll:before{content:"\f70e"}.fa-sd-card:before{content:"\f7c2"}.fa-search:before{content:"\f002"}.fa-search-dollar:before{content:"\f688"}.fa-search-location:before{content:"\f689"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-shapes:before{content:"\f61f"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-sim-card:before{content:"\f7c4"}.fa-simplybuilt:before{content:"\f215"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skating:before{content:"\f7c5"}.fa-sketch:before{content:"\f7c6"}.fa-skiing:before{content:"\f7c9"}.fa-skiing-nordic:before{content:"\f7ca"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-slash:before{content:"\f715"}.fa-sleigh:before{content:"\f7cc"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-sms:before{content:"\f7cd"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowboarding:before{content:"\f7ce"}.fa-snowflake:before{content:"\f2dc"}.fa-snowman:before{content:"\f7d0"}.fa-snowplow:before{content:"\f7d2"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-down-alt:before{content:"\f884"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-amount-up-alt:before{content:"\f885"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-sourcetree:before{content:"\f7d3"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-speaker-deck:before{content:"\f83c"}.fa-spell-check:before{content:"\f891"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-square-root-alt:before{content:"\f698"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stackpath:before{content:"\f842"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-suse:before{content:"\f7d6"}.fa-swatchbook:before{content:"\f5c3"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-symfony:before{content:"\f83d"}.fa-synagogue:before{content:"\f69b"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-tenge:before{content:"\f7d7"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-the-red-yeti:before{content:"\f69d"}.fa-theater-masks:before{content:"\f630"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-think-peaks:before{content:"\f731"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet:before{content:"\f7d8"}.fa-toilet-paper:before{content:"\f71e"}.fa-toolbox:before{content:"\f552"}.fa-tools:before{content:"\f7d9"}.fa-tooth:before{content:"\f5c9"}.fa-torah:before{content:"\f6a0"}.fa-torii-gate:before{content:"\f6a1"}.fa-tractor:before{content:"\f722"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-train:before{content:"\f238"}.fa-tram:before{content:"\f7da"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-trash-restore:before{content:"\f829"}.fa-trash-restore-alt:before{content:"\f82a"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-tripadvisor:before{content:"\f262"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-ubuntu:before{content:"\f7df"}.fa-uikit:before{content:"\f403"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-ups:before{content:"\f7e0"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-injured:before{content:"\f728"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-nurse:before{content:"\f82f"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-usps:before{content:"\f7e1"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-voicemail:before{content:"\f897"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-mute:before{content:"\f6a9"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vote-yea:before{content:"\f772"}.fa-vr-cardboard:before{content:"\f729"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-water:before{content:"\f773"}.fa-wave-square:before{content:"\f83e"}.fa-waze:before{content:"\f83f"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-wind:before{content:"\f72e"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yammer:before{content:"\f840"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yarn:before{content:"\f7e3"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}/*!* Font Awesome Free 5.10.1 by @fontawesome - https://fontawesome.com +* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)*/@font-face{font-family:'font awesome 5 free';font-style:normal;font-weight:900;font-display:auto;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.fas{font-family:'font awesome 5 free';font-weight:900}/*!* Font Awesome Free 5.10.1 by @fontawesome - https://fontawesome.com +* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)*/@font-face{font-family:'font awesome 5 brands';font-style:normal;font-weight:400;font-display:auto;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:'font awesome 5 brands'}.td-border-top{border:none;border-top:1px solid #eee}.td-border-none{border:none}.td-block-padding,.td-default main section{padding-top:4rem;padding-bottom:4rem}@media(min-width:768px){.td-block-padding,.td-default main section{padding-top:5rem;padding-bottom:5rem}}.td-overlay{position:relative}.td-overlay::after{content:"";position:absolute;top:0;right:0;bottom:0;left:0}.td-overlay--dark::after{background-color:rgba(64,63,76,.3)}.td-overlay--light::after{background-color:rgba(211,243,238,.3)}.td-overlay__inner{position:relative;z-index:1}@media(min-width:992px){.td-max-width-on-larger-screens,.td-content>pre,.td-content>.highlight,.td-content>.lead,.td-content>h1,.td-content>h2,.td-content>ul,.td-content>ol,.td-content>p,.td-content>blockquote,.td-content>dl dd,.td-content .footnotes,.td-content>.alert{max-width:80%}}.td-box--height-min{min-height:300px}.td-box--height-med{min-height:400px}.td-box--height-max{min-height:500px}.td-box--height-full{min-height:100vh}@media(min-width:768px){.td-box--height-min{min-height:450px}.td-box--height-med{min-height:500px}.td-box--height-max{min-height:650px}}.td-box .row.section{padding-left:5rem;padding-right:5rem;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.td-box .row{padding-left:5rem;padding-right:5rem;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.td-box.linkbox{padding:5rem}.td-box--0{color:#fff;background-color:#403f4c}.td-box--0 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#403f4c transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--0 p>a{color:#d9e5f8}.td-box--10.td-box--gradient{background:#403F4C -webkit-gradient(linear,left top,left bottom,from(#5d5c67),to(#403F4C)) repeat-x!important;background:#403f4c -webkit-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c -o-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c linear-gradient(180deg,#5d5c67,#403F4C) repeat-x!important}.td-box--1{color:#fff;background-color:#30638e}.td-box--1 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#30638e transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--1 p>a{color:#cadcf5}.td-box--11.td-box--gradient{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x!important;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x!important}.td-box--2{color:#fff;background-color:#ffa630}.td-box--2 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ffa630 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--2 p>a{color:#abc7f0}.td-box--12.td-box--gradient{background:#FFA630 -webkit-gradient(linear,left top,left bottom,from(#ffb34f),to(#FFA630)) repeat-x!important;background:#ffa630 -webkit-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 -o-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 linear-gradient(180deg,#ffb34f,#FFA630) repeat-x!important}.td-box--3{color:#222;background-color:#c0e0de}.td-box--3 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#c0e0de transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--3 p>a{color:#638ac1}.td-box--13.td-box--gradient{background:#C0E0DE -webkit-gradient(linear,left top,left bottom,from(#c9e5e3),to(#C0E0DE)) repeat-x!important;background:#c0e0de -webkit-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de -o-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de linear-gradient(180deg,#c9e5e3,#C0E0DE) repeat-x!important}.td-box--4{color:#222;background-color:#fff}.td-box--4 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#fff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--4 p>a{color:#72a1e5}.td-box--14.td-box--gradient{background:white -webkit-gradient(linear,left top,left bottom,from(white),to(white)) repeat-x!important;background:#fff -webkit-linear-gradient(top,white,white) repeat-x!important;background:#fff -o-linear-gradient(top,white,white) repeat-x!important;background:#fff linear-gradient(180deg,white,white) repeat-x!important}.td-box--5{color:#fff;background-color:#888}.td-box--5 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#888 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--5 p>a{color:#b4cdf1}.td-box--15.td-box--gradient{background:#888 -webkit-gradient(linear,left top,left bottom,from(#9a9a9a),to(#888)) repeat-x!important;background:#888 -webkit-linear-gradient(top,#9a9a9a,#888) repeat-x!important;background:#888 -o-linear-gradient(top,#9a9a9a,#888) repeat-x!important;background:#888 linear-gradient(180deg,#9a9a9a,#888) repeat-x!important}.td-box--6{color:#fff;background-color:#3772ff}.td-box--6 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#3772ff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--6 p>a{color:#a9c6ef}.td-box--16.td-box--gradient{background:#3772FF -webkit-gradient(linear,left top,left bottom,from(#5587ff),to(#3772FF)) repeat-x!important;background:#3772ff -webkit-linear-gradient(top,#5587ff,#3772FF) repeat-x!important;background:#3772ff -o-linear-gradient(top,#5587ff,#3772FF) repeat-x!important;background:#3772ff linear-gradient(180deg,#5587ff,#3772FF) repeat-x!important}.td-box--7{color:#fff;background-color:#ed6a5a}.td-box--7 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ed6a5a transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--7 p>a{color:#a5c3ee}.td-box--17.td-box--gradient{background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x!important;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x!important}.td-box--8{color:#fff;background-color:#403f4c}.td-box--8 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#403f4c transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--8 p>a{color:#d9e5f8}.td-box--18.td-box--gradient{background:#403F4C -webkit-gradient(linear,left top,left bottom,from(#5d5c67),to(#403F4C)) repeat-x!important;background:#403f4c -webkit-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c -o-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c linear-gradient(180deg,#5d5c67,#403F4C) repeat-x!important}.td-box--9{color:#fff;background-color:#ed6a5a}.td-box--9 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ed6a5a transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--9 p>a{color:#a5c3ee}.td-box--19.td-box--gradient{background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x!important;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x!important}.td-box--10{color:#fff;background-color:#30638e}.td-box--10 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#30638e transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--10 p>a{color:#cadcf5}.td-box--110.td-box--gradient{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x!important;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x!important}.td-box--11{color:#fff;background-color:#ffa630}.td-box--11 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ffa630 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--11 p>a{color:#abc7f0}.td-box--111.td-box--gradient{background:#FFA630 -webkit-gradient(linear,left top,left bottom,from(#ffb34f),to(#FFA630)) repeat-x!important;background:#ffa630 -webkit-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 -o-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 linear-gradient(180deg,#ffb34f,#FFA630) repeat-x!important}.td-box--12{color:#222;background-color:#fff}.td-box--12 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#fff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--12 p>a{color:#72a1e5}.td-box--112.td-box--gradient{background:white -webkit-gradient(linear,left top,left bottom,from(white),to(white)) repeat-x!important;background:#fff -webkit-linear-gradient(top,white,white) repeat-x!important;background:#fff -o-linear-gradient(top,white,white) repeat-x!important;background:#fff linear-gradient(180deg,white,white) repeat-x!important}.td-box--13{color:#222;background-color:#c0e0de}.td-box--13 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#c0e0de transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--13 p>a{color:#638ac1}.td-box--113.td-box--gradient{background:#C0E0DE -webkit-gradient(linear,left top,left bottom,from(#c9e5e3),to(#C0E0DE)) repeat-x!important;background:#c0e0de -webkit-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de -o-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de linear-gradient(180deg,#c9e5e3,#C0E0DE) repeat-x!important}.td-box--cerulean-blue{color:#fff;background-color:#017cee}.td-box--cerulean-blue .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#017cee transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--cerulean-blue p>a{color:#bdd3f3}.td-box--1cerulean-blue.td-box--gradient{background:#017cee -webkit-gradient(linear,left top,left bottom,from(#2790f1),to(#017cee)) repeat-x!important;background:#017cee -webkit-linear-gradient(top,#2790f1,#017cee) repeat-x!important;background:#017cee -o-linear-gradient(top,#2790f1,#017cee) repeat-x!important;background:#017cee linear-gradient(180deg,#2790f1,#017cee) repeat-x!important}.td-box--shamrock{color:#fff;background-color:#00ad46}.td-box--shamrock .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#00ad46 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--shamrock p>a{color:#cfdff6}.td-box--1shamrock.td-box--gradient{background:#00ad46 -webkit-gradient(linear,left top,left bottom,from(#26b962),to(#00ad46)) repeat-x!important;background:#00ad46 -webkit-linear-gradient(top,#26b962,#00ad46) repeat-x!important;background:#00ad46 -o-linear-gradient(top,#26b962,#00ad46) repeat-x!important;background:#00ad46 linear-gradient(180deg,#26b962,#00ad46) repeat-x!important}.td-box--bright-sky-blue{color:#fff;background-color:#0cb6ff}.td-box--bright-sky-blue .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#0cb6ff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--bright-sky-blue p>a{color:#b5cef1}.td-box--1bright-sky-blue.td-box--gradient{background:#0cb6ff -webkit-gradient(linear,left top,left bottom,from(#30c1ff),to(#0cb6ff)) repeat-x!important;background:#0cb6ff -webkit-linear-gradient(top,#30c1ff,#0cb6ff) repeat-x!important;background:#0cb6ff -o-linear-gradient(top,#30c1ff,#0cb6ff) repeat-x!important;background:#0cb6ff linear-gradient(180deg,#30c1ff,#0cb6ff) repeat-x!important}.td-box--melon{color:#fff;background-color:#ff7557}.td-box--melon .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ff7557 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--melon p>a{color:#a0c0ee}.td-box--1melon.td-box--gradient{background:#ff7557 -webkit-gradient(linear,left top,left bottom,from(#ff8a70),to(#ff7557)) repeat-x!important;background:#ff7557 -webkit-linear-gradient(top,#ff8a70,#ff7557) repeat-x!important;background:#ff7557 -o-linear-gradient(top,#ff8a70,#ff7557) repeat-x!important;background:#ff7557 linear-gradient(180deg,#ff8a70,#ff7557) repeat-x!important}.td-box--vermillion{color:#fff;background-color:#e43921}.td-box--vermillion .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#e43921 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--vermillion p>a{color:#b7cff2}.td-box--1vermillion.td-box--gradient{background:#e43921 -webkit-gradient(linear,left top,left bottom,from(#e85742),to(#e43921)) repeat-x!important;background:#e43921 -webkit-linear-gradient(top,#e85742,#e43921) repeat-x!important;background:#e43921 -o-linear-gradient(top,#e85742,#e43921) repeat-x!important;background:#e43921 linear-gradient(180deg,#e85742,#e43921) repeat-x!important}.td-box--aqua{color:#fff;background-color:#11e1ee}.td-box--aqua .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#11e1ee transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--aqua p>a{color:#b9d0f2}.td-box--1aqua.td-box--gradient{background:#11e1ee -webkit-gradient(linear,left top,left bottom,from(#35e6f1),to(#11e1ee)) repeat-x!important;background:#11e1ee -webkit-linear-gradient(top,#35e6f1,#11e1ee) repeat-x!important;background:#11e1ee -o-linear-gradient(top,#35e6f1,#11e1ee) repeat-x!important;background:#11e1ee linear-gradient(180deg,#35e6f1,#11e1ee) repeat-x!important}.td-box--shamrock-green{color:#fff;background-color:#04d659}.td-box--shamrock-green .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#04d659 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--shamrock-green p>a{color:#c3d7f4}.td-box--1shamrock-green.td-box--gradient{background:#04d659 -webkit-gradient(linear,left top,left bottom,from(#2adc72),to(#04d659)) repeat-x!important;background:#04d659 -webkit-linear-gradient(top,#2adc72,#04d659) repeat-x!important;background:#04d659 -o-linear-gradient(top,#2adc72,#04d659) repeat-x!important;background:#04d659 linear-gradient(180deg,#2adc72,#04d659) repeat-x!important}.td-box--aqua-blue{color:#fff;background-color:#00c7d4}.td-box--aqua-blue .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#00c7d4 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--aqua-blue p>a{color:#c4d8f4}.td-box--1aqua-blue.td-box--gradient{background:#00c7d4 -webkit-gradient(linear,left top,left bottom,from(#26cfda),to(#00c7d4)) repeat-x!important;background:#00c7d4 -webkit-linear-gradient(top,#26cfda,#00c7d4) repeat-x!important;background:#00c7d4 -o-linear-gradient(top,#26cfda,#00c7d4) repeat-x!important;background:#00c7d4 linear-gradient(180deg,#26cfda,#00c7d4) repeat-x!important}.td-box--white{color:#222;background-color:#fff}.td-box--white .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#fff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--white p>a{color:#72a1e5}.td-box--1white.td-box--gradient{background:#ffffff -webkit-gradient(linear,left top,left bottom,from(white),to(#ffffff)) repeat-x!important;background:#fff -webkit-linear-gradient(top,white,#ffffff) repeat-x!important;background:#fff -o-linear-gradient(top,white,#ffffff) repeat-x!important;background:#fff linear-gradient(180deg,white,#ffffff) repeat-x!important}.td-box--brownish-grey{color:#fff;background-color:#707070}.td-box--brownish-grey .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#707070 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--brownish-grey p>a{color:#c1d6f4}.td-box--1brownish-grey.td-box--gradient{background:#707070 -webkit-gradient(linear,left top,left bottom,from(#858585),to(#707070)) repeat-x!important;background:#707070 -webkit-linear-gradient(top,#858585,#707070) repeat-x!important;background:#707070 -o-linear-gradient(top,#858585,#707070) repeat-x!important;background:#707070 linear-gradient(180deg,#858585,#707070) repeat-x!important}.td-box--very-light-pink{color:#222;background-color:#cbcbcb}.td-box--very-light-pink .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#cbcbcb transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--very-light-pink p>a{color:#6287bd}.td-box--1very-light-pink.td-box--gradient{background:#cbcbcb -webkit-gradient(linear,left top,left bottom,from(lightgray),to(#cbcbcb)) repeat-x!important;background:#cbcbcb -webkit-linear-gradient(top,lightgray,#cbcbcb) repeat-x!important;background:#cbcbcb -o-linear-gradient(top,lightgray,#cbcbcb) repeat-x!important;background:#cbcbcb linear-gradient(180deg,lightgray,#cbcbcb) repeat-x!important}.td-box--slate-grey{color:#fff;background-color:#636365}.td-box--slate-grey .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#636365 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--slate-grey p>a{color:#c8daf5}.td-box--1slate-grey.td-box--gradient{background:#636365 -webkit-gradient(linear,left top,left bottom,from(#7a7a7c),to(#636365)) repeat-x!important;background:#636365 -webkit-linear-gradient(top,#7a7a7c,#636365) repeat-x!important;background:#636365 -o-linear-gradient(top,#7a7a7c,#636365) repeat-x!important;background:#636365 linear-gradient(180deg,#7a7a7c,#636365) repeat-x!important}.td-box--greyish-brown{color:#fff;background-color:#51504f}.td-box--greyish-brown .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#51504f transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--greyish-brown p>a{color:#d3e2f7}.td-box--1greyish-brown.td-box--gradient{background:#51504f -webkit-gradient(linear,left top,left bottom,from(#6b6a69),to(#51504f)) repeat-x!important;background:#51504f -webkit-linear-gradient(top,#6b6a69,#51504f) repeat-x!important;background:#51504f -o-linear-gradient(top,#6b6a69,#51504f) repeat-x!important;background:#51504f linear-gradient(180deg,#6b6a69,#51504f) repeat-x!important}.td-box--primary{color:#fff;background-color:#30638e}.td-box--primary .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#30638e transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--primary p>a{color:#cadcf5}.td-box--1primary.td-box--gradient{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x!important;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x!important}.td-box--secondary{color:#fff;background-color:#ffa630}.td-box--secondary .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ffa630 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--secondary p>a{color:#abc7f0}.td-box--1secondary.td-box--gradient{background:#FFA630 -webkit-gradient(linear,left top,left bottom,from(#ffb34f),to(#FFA630)) repeat-x!important;background:#ffa630 -webkit-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 -o-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 linear-gradient(180deg,#ffb34f,#FFA630) repeat-x!important}.td-box--success{color:#fff;background-color:#3772ff}.td-box--success .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#3772ff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--success p>a{color:#a9c6ef}.td-box--1success.td-box--gradient{background:#3772FF -webkit-gradient(linear,left top,left bottom,from(#5587ff),to(#3772FF)) repeat-x!important;background:#3772ff -webkit-linear-gradient(top,#5587ff,#3772FF) repeat-x!important;background:#3772ff -o-linear-gradient(top,#5587ff,#3772FF) repeat-x!important;background:#3772ff linear-gradient(180deg,#5587ff,#3772FF) repeat-x!important}.td-box--info{color:#222;background-color:#c0e0de}.td-box--info .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#c0e0de transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--info p>a{color:#638ac1}.td-box--1info.td-box--gradient{background:#C0E0DE -webkit-gradient(linear,left top,left bottom,from(#c9e5e3),to(#C0E0DE)) repeat-x!important;background:#c0e0de -webkit-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de -o-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de linear-gradient(180deg,#c9e5e3,#C0E0DE) repeat-x!important}.td-box--warning{color:#fff;background-color:#ed6a5a}.td-box--warning .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ed6a5a transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--warning p>a{color:#a5c3ee}.td-box--1warning.td-box--gradient{background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x!important;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x!important}.td-box--danger{color:#fff;background-color:#ed6a5a}.td-box--danger .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ed6a5a transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--danger p>a{color:#a5c3ee}.td-box--1danger.td-box--gradient{background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x!important;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x!important}.td-box--light{color:#222;background-color:#d3f3ee}.td-box--light .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#d3f3ee transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--light p>a{color:#6993d0}.td-box--1light.td-box--gradient{background:#D3F3EE -webkit-gradient(linear,left top,left bottom,from(#daf5f1),to(#D3F3EE)) repeat-x!important;background:#d3f3ee -webkit-linear-gradient(top,#daf5f1,#D3F3EE) repeat-x!important;background:#d3f3ee -o-linear-gradient(top,#daf5f1,#D3F3EE) repeat-x!important;background:#d3f3ee linear-gradient(180deg,#daf5f1,#D3F3EE) repeat-x!important}.td-box--dark{color:#fff;background-color:#403f4c}.td-box--dark .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#403f4c transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--dark p>a{color:#d9e5f8}.td-box--1dark.td-box--gradient{background:#403F4C -webkit-gradient(linear,left top,left bottom,from(#5d5c67),to(#403F4C)) repeat-x!important;background:#403f4c -webkit-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c -o-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c linear-gradient(180deg,#5d5c67,#403F4C) repeat-x!important}.td-box--100{color:#222;background-color:#f8f9fa}.td-box--100 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#f8f9fa transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--100 p>a{color:#709ee0}.td-box--1100.td-box--gradient{background:#f8f9fa -webkit-gradient(linear,left top,left bottom,from(#f9fafb),to(#f8f9fa)) repeat-x!important;background:#f8f9fa -webkit-linear-gradient(top,#f9fafb,#f8f9fa) repeat-x!important;background:#f8f9fa -o-linear-gradient(top,#f9fafb,#f8f9fa) repeat-x!important;background:#f8f9fa linear-gradient(180deg,#f9fafb,#f8f9fa) repeat-x!important}.td-box--200{color:#222;background-color:#eee}.td-box--200 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#eee transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--200 p>a{color:#6d99d8}.td-box--1200.td-box--gradient{background:#eee -webkit-gradient(linear,left top,left bottom,from(#f1f1f1),to(#eee)) repeat-x!important;background:#eee -webkit-linear-gradient(top,#f1f1f1,#eee) repeat-x!important;background:#eee -o-linear-gradient(top,#f1f1f1,#eee) repeat-x!important;background:#eee linear-gradient(180deg,#f1f1f1,#eee) repeat-x!important}.td-box--300{color:#222;background-color:#dee2e6}.td-box--300 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#dee2e6 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--300 p>a{color:#6993cf}.td-box--1300.td-box--gradient{background:#dee2e6 -webkit-gradient(linear,left top,left bottom,from(#e3e6ea),to(#dee2e6)) repeat-x!important;background:#dee2e6 -webkit-linear-gradient(top,#e3e6ea,#dee2e6) repeat-x!important;background:#dee2e6 -o-linear-gradient(top,#e3e6ea,#dee2e6) repeat-x!important;background:#dee2e6 linear-gradient(180deg,#e3e6ea,#dee2e6) repeat-x!important}.td-box--400{color:#222;background-color:#ccc}.td-box--400 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ccc transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--400 p>a{color:#6288be}.td-box--1400.td-box--gradient{background:#ccc -webkit-gradient(linear,left top,left bottom,from(#d4d4d4),to(#ccc)) repeat-x!important;background:#ccc -webkit-linear-gradient(top,#d4d4d4,#ccc) repeat-x!important;background:#ccc -o-linear-gradient(top,#d4d4d4,#ccc) repeat-x!important;background:#ccc linear-gradient(180deg,#d4d4d4,#ccc) repeat-x!important}.td-box--500{color:#fff;background-color:#adb5bd}.td-box--500 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#adb5bd transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--500 p>a{color:#9bbced}.td-box--1500.td-box--gradient{background:#adb5bd -webkit-gradient(linear,left top,left bottom,from(#b9c0c7),to(#adb5bd)) repeat-x!important;background:#adb5bd -webkit-linear-gradient(top,#b9c0c7,#adb5bd) repeat-x!important;background:#adb5bd -o-linear-gradient(top,#b9c0c7,#adb5bd) repeat-x!important;background:#adb5bd linear-gradient(180deg,#b9c0c7,#adb5bd) repeat-x!important}.td-box--600{color:#fff;background-color:#888}.td-box--600 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#888 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--600 p>a{color:#b4cdf1}.td-box--1600.td-box--gradient{background:#888 -webkit-gradient(linear,left top,left bottom,from(#9a9a9a),to(#888)) repeat-x!important;background:#888 -webkit-linear-gradient(top,#9a9a9a,#888) repeat-x!important;background:#888 -o-linear-gradient(top,#9a9a9a,#888) repeat-x!important;background:#888 linear-gradient(180deg,#9a9a9a,#888) repeat-x!important}.td-box--700{color:#fff;background-color:#495057}.td-box--700 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#495057 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--700 p>a{color:#d3e2f7}.td-box--1700.td-box--gradient{background:#495057 -webkit-gradient(linear,left top,left bottom,from(#646a70),to(#495057)) repeat-x!important;background:#495057 -webkit-linear-gradient(top,#646a70,#495057) repeat-x!important;background:#495057 -o-linear-gradient(top,#646a70,#495057) repeat-x!important;background:#495057 linear-gradient(180deg,#646a70,#495057) repeat-x!important}.td-box--800{color:#fff;background-color:#333}.td-box--800 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#333 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--800 p>a{color:#e3ecfa}.td-box--1800.td-box--gradient{background:#333 -webkit-gradient(linear,left top,left bottom,from(#525252),to(#333)) repeat-x!important;background:#333 -webkit-linear-gradient(top,#525252,#333) repeat-x!important;background:#333 -o-linear-gradient(top,#525252,#333) repeat-x!important;background:#333 linear-gradient(180deg,#525252,#333) repeat-x!important}.td-box--900{color:#fff;background-color:#222}.td-box--900 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#222 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--900 p>a{color:#ecf2fc}.td-box--1900.td-box--gradient{background:#222 -webkit-gradient(linear,left top,left bottom,from(#434343),to(#222)) repeat-x!important;background:#222 -webkit-linear-gradient(top,#434343,#222) repeat-x!important;background:#222 -o-linear-gradient(top,#434343,#222) repeat-x!important;background:#222 linear-gradient(180deg,#434343,#222) repeat-x!important}.td-blog .td-rss-button{position:absolute;top:5.5rem;right:1rem;z-index:22}.td-content .highlight{margin:2rem 0;padding:1rem;background-color:#f8f9fa}.td-content .highlight pre,.td-content .highlight div{background-color:inherit!important}.td-content .highlight pre{margin:0;padding:0}.td-content p code,.td-content li>code,.td-content table code{color:inherit;padding:.2em .4em;margin:0;font-size:85%;word-break:normal;background-color:rgba(0,0,0,.05);border-radius:.25rem}.td-content p code br,.td-content li>code br,.td-content table code br{display:none}.td-content pre{word-wrap:normal;background-color:#f8f9fa;padding:1rem}.td-content pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;border:0}.td-navbar-cover{background:#30638e}@media(min-width:768px){.td-navbar-cover{background:transparent!important}.td-navbar-cover .nav-link{text-shadow:1px 1px 2px #403f4c}}.td-navbar-cover.navbar-bg-onscroll .nav-link{text-shadow:none}.navbar-bg-onscroll{background:#30638e!important;opacity:inherit}.td-navbar{background:#30638e;min-height:4rem;margin:0;z-index:32}@media(min-width:768px){.td-navbar{position:fixed;top:0;width:100%}}.td-navbar .navbar-brand{text-transform:none;text-align:middle}.td-navbar .navbar-brand .nav-link{display:inline-block;margin-right:-30px}.td-navbar .navbar-brand svg{display:inline-block;margin:0 10px;height:30px}.td-navbar .nav-link{text-transform:none;font-weight:700}.td-navbar .td-search-input{border:none}.td-navbar .td-search-input::-webkit-input-placeholder{color:rgba(255,255,255,.75)}.td-navbar .td-search-input:-moz-placeholder{color:rgba(255,255,255,.75)}.td-navbar .td-search-input::-moz-placeholder{color:rgba(255,255,255,.75)}.td-navbar .td-search-input:-ms-input-placeholder{color:rgba(255,255,255,.75)}.td-navbar .dropdown{min-width:100px}@media(max-width:991.98px){.td-navbar{padding-right:.5rem;padding-left:.75rem}.td-navbar .td-navbar-nav-scroll{max-width:100%;height:2.5rem;margin-top:.25rem;overflow:hidden;font-size:.875rem}.td-navbar .td-navbar-nav-scroll .nav-link{padding-right:.25rem;padding-left:0}.td-navbar .td-navbar-nav-scroll .navbar-nav{padding-bottom:2rem;overflow-x:auto;white-space:nowrap;-webkit-overflow-scrolling:touch}}.td-sidebar-nav{padding-right:.5rem;margin-right:-15px;margin-left:-15px}@media(min-width:768px){@supports((position:-webkit-sticky) or (position:sticky)){.td-sidebar-nav{max-height:-webkit-calc(100vh - 10rem);max-height:calc(100vh - 10rem);overflow-y:auto}}}@media(min-width:768px){.td-sidebar-nav{display:block!important}}.td-sidebar-nav__section{padding-left:0}.td-sidebar-nav__section li{list-style:none}.td-sidebar-nav__section ul{padding:0;margin:0}@media(min-width:768px){.td-sidebar-nav__section>ul{padding-left:.5rem}}.td-sidebar-nav__section-title{display:block;font-weight:500}.td-sidebar-nav__section-title .active{font-weight:700}.td-sidebar-nav__section-title a{color:#222}.td-sidebar-nav .td-sidebar-link{display:block;padding-bottom:.375rem}.td-sidebar-nav .td-sidebar-link__page{color:#495057;font-weight:300}.td-sidebar-nav a:hover{color:#72a1e5;text-decoration:none}.td-sidebar-nav a.active{font-weight:700}.td-sidebar-nav .dropdown a{color:#495057}.td-sidebar-nav .dropdown .nav-link{padding:0 0 1rem}.td-sidebar{padding-bottom:1rem}@media(min-width:768px){.td-sidebar{padding-top:4rem;background-color:rgba(48,99,142,.03);padding-right:1rem;border-right:1px solid #dee2e6}}.td-sidebar__toggle{line-height:1;color:#222;margin:1rem}.td-sidebar__search{padding:1rem 15px;margin-right:-15px;margin-left:-15px}.td-sidebar__inner{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}@media(min-width:768px){@supports((position:-webkit-sticky) or (position:sticky)){.td-sidebar__inner{position:-webkit-sticky;position:sticky;top:4rem;z-index:10;height:-webkit-calc(100vh - 6rem);height:calc(100vh - 6rem)}}}@media(min-width:1200px){.td-sidebar__inner{-webkit-box-flex:0;-webkit-flex:0 1 320px;-ms-flex:0 1 320px;flex:0 1 320px}}.td-sidebar__inner .td-search-box{width:100%}.td-toc{border-left:1px solid #dee2e6;-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2;padding-top:.75rem;padding-bottom:1.5rem;vertical-align:top}@supports((position:-webkit-sticky) or (position:sticky)){.td-toc{position:-webkit-sticky;position:sticky;top:4rem;height:-webkit-calc(100vh - 10rem);height:calc(100vh - 10rem);overflow-y:auto}}.td-toc a{display:block;font-weight:300;padding-bottom:.25rem}.td-toc li{list-style:none;display:block}.td-toc li li{margin-left:.5rem}.td-toc .td-page-meta a{font-weight:500}.td-toc #TableOfContents a{color:#888}.td-toc #TableOfContents a:hover{color:#72a1e5;text-decoration:none}.td-toc ul{padding-left:0}button{cursor:pointer;border:1px solid;border-radius:5px;padding:9px 29px;-webkit-transition:all ease-out .2s;-o-transition:all ease-out .2s;transition:all ease-out .2s}button:disabled{cursor:not-allowed}button.btn-filled{border-color:#017cee;background-color:#017cee}button.btn-filled:hover{border-color:#0cb6ff;background-color:#0cb6ff}button.btn-with-icon{padding:14px 20px}button.btn-with-icon svg{height:30px;width:auto;padding-right:15px}button.btn-with-icon span{display:inline-block;line-height:30px;vertical-align:middle}button.btn-hollow{background-color:#fff}button.btn-hollow.btn-blue{color:#017cee;border-color:#017cee}button.btn-hollow.btn-blue:disabled{color:#cbcbcb;border-color:#cbcbcb}button.btn-hollow.btn-blue:hover:enabled{color:#fff;background-color:#017cee}button.btn-hollow.btn-brown{border-color:#cbcbcb}button.btn-hollow.btn-brown:hover{background-color:#51504f;border-color:#51504f}button.btn-hollow.btn-brown:hover span{color:#fff}button.btn-hollow.btn-brown:hover svg path{fill:#fff}button.with-box-shadow{-webkit-box-shadow:0 2px 6px 0 rgba(0,0,0,.12);box-shadow:0 2px 6px 0 rgba(0,0,0,.12)}@media(max-width:1280px){button{padding:4px 17px}}.breadcrumb{background:0 0;padding-left:0;padding-top:0}.alert{font-weight:500;background:#fff;color:inherit;border-radius:0}.alert-primary{border-style:solid;border-color:#30638e;border-width:0 0 0 4px}.alert-primary .alert-heading{color:#30638e}.alert-secondary{border-style:solid;border-color:#ffa630;border-width:0 0 0 4px}.alert-secondary .alert-heading{color:#ffa630}.alert-success{border-style:solid;border-color:#3772ff;border-width:0 0 0 4px}.alert-success .alert-heading{color:#3772ff}.alert-info{border-style:solid;border-color:#c0e0de;border-width:0 0 0 4px}.alert-info .alert-heading{color:#c0e0de}.alert-warning{border-style:solid;border-color:#ed6a5a;border-width:0 0 0 4px}.alert-warning .alert-heading{color:#ed6a5a}.alert-danger{border-style:solid;border-color:#ed6a5a;border-width:0 0 0 4px}.alert-danger .alert-heading{color:#ed6a5a}.alert-light{border-style:solid;border-color:#d3f3ee;border-width:0 0 0 4px}.alert-light .alert-heading{color:#d3f3ee}.alert-dark{border-style:solid;border-color:#403f4c;border-width:0 0 0 4px}.alert-dark .alert-heading{color:#403f4c}.td-content{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.td-content p,.td-content li,.td-content td{font-weight:400}.td-content>h1{font-weight:700;margin-bottom:1rem}.td-content>h2{margin-bottom:1rem}.td-content>h2:not(:first-child){margin-top:3rem}.td-content>h2+h3{margin-top:1rem}.td-content>h3,.td-content>h4,.td-content>h5,.td-content>h6{margin-bottom:1rem;margin-top:2rem}.td-content>blockquote{padding:0 0 0 1rem;margin-bottom:1rem;color:#888;border-left:6px solid #ffa630}.td-content>ul li,.td-content>ol li{margin-bottom:.25rem}.td-content strong{font-weight:700}.td-content .alert:not(:first-child){margin-top:2rem;margin-bottom:2rem}.td-content .lead{margin-bottom:1.5rem}.td-title{margin-top:1rem;margin-bottom:.5rem}@media(min-width:576px){.td-title{font-size:3rem}}.search-form{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:344px;padding:8px 20px;border:solid 1px #cbcbcb;border-radius:5px;margin:60px auto 0}.search-form__input{font-family:roboto,sans-serif;font-size:16px;color:#707070;line-height:1.63;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;padding-right:10px;border:none;background:0 0;outline:none;float:left}.search-form__button{border:none;background-color:transparent;padding:0}@media(max-width:1280px){.search-form{width:270px;padding:3px 20px;margin-top:30px}}.td-outer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;height:100vh}@media(min-width:768px){.td-default main section:first-of-type{padding-top:8rem}}.td-main{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1}.td-main main{padding-bottom:2rem}@media(min-width:768px){.td-main main{padding-top:5.5rem}}.td-cover-block--height-min{min-height:300px}.td-cover-block--height-med{min-height:400px}.td-cover-block--height-max{min-height:500px}.td-cover-block--height-full{min-height:100vh}@media(min-width:768px){.td-cover-block--height-min{min-height:450px}.td-cover-block--height-med{min-height:500px}.td-cover-block--height-max{min-height:650px}}.td-cover-logo{margin-right:.5em}.td-cover-block{position:relative;padding-top:5rem;padding-bottom:5rem;background-repeat:no-repeat;background-position:50% 0;-webkit-background-size:cover;background-size:cover}.td-bg-arrow-wrapper{position:relative}.section-index .entry{padding:.75rem}.section-index h5{margin-bottom:0}.section-index h5 a{font-weight:700}.section-index p{margin-top:0}.pageinfo{font-weight:500;background:#f8f9fa;color:inherit;border-radius:0;margin:2rem;padding:1.5rem;padding-bottom:.5rem}.pageinfo-primary{border-style:solid;border-color:#30638e}.pageinfo-secondary{border-style:solid;border-color:#ffa630}.pageinfo-success{border-style:solid;border-color:#3772ff}.pageinfo-info{border-style:solid;border-color:#c0e0de}.pageinfo-warning{border-style:solid;border-color:#ed6a5a}.pageinfo-danger{border-style:solid;border-color:#ed6a5a}.pageinfo-light{border-style:solid;border-color:#d3f3ee}.pageinfo-dark{border-style:solid;border-color:#403f4c}footer{min-height:150px}@media(max-width:991.98px){footer{min-height:200px}}@media(min-width:768px){.td-offset-anchor:target{display:block;position:relative;top:-4rem;visibility:hidden}h2[id]:before,h3[id]:before,h4[id]:before,h5[id]:before{display:block;content:" ";margin-top:-5rem;height:5rem;visibility:hidden}} \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/_gen/js/docs.js b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/_gen/js/docs.js new file mode 100644 index 00000000000..90898d86d50 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/_gen/js/docs.js @@ -0,0 +1 @@ +!function(r){var n={};function o(t){if(n[t])return n[t].exports;var e=n[t]={i:t,l:!1,exports:{}};return r[t].call(e.exports,e,e.exports,o),e.l=!0,e.exports}o.m=r,o.c=n,o.d=function(t,e,r){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(o.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)o.d(r,n,function(t){return e[t]}.bind(null,n));return r},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o.p="/",o(o.s=54)}([function(t,e,r){var m=r(1),w=r(14),g=r(15),E=Math.max,x=Math.min;t.exports=function(n,r,t){var o,i,a,s,u,c,f=0,l=!1,d=!1,e=!0;if("function"!=typeof n)throw new TypeError("Expected a function");function h(t){var e=o,r=i;return o=i=void 0,f=t,s=n.apply(r,e)}function p(t){var e=t-c;return void 0===c||r<=e||e<0||d&&a<=t-f}function y(){var t=w();if(p(t))return b(t);u=setTimeout(y,function(t){var e=r-(t-c);return d?x(e,a-(t-f)):e}(t))}function b(t){return u=void 0,e&&o?h(t):(o=i=void 0,s)}function v(){var t=w(),e=p(t);if(o=arguments,i=this,c=t,e){if(void 0===u)return function(t){return f=t,u=setTimeout(y,r),l?h(t):s}(c);if(d)return clearTimeout(u),u=setTimeout(y,r),h(c)}return void 0===u&&(u=setTimeout(y,r)),s}return r=g(r)||0,m(t)&&(l=!!t.leading,a=(d="maxWait"in t)?E(g(t.maxWait)||0,r):a,e="trailing"in t?!!t.trailing:e),v.cancel=function(){void 0!==u&&clearTimeout(u),o=c=i=u=void(f=0)},v.flush=function(){return void 0===u?s:b(w())},v}},function(t,e){t.exports=function(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}},function(t,e,r){var n=r(8),o="object"==typeof self&&self&&self.Object===Object&&self,i=n||o||Function("return this")();t.exports=i},function(t,e,r){var n=r(6),o=r(17),i=r(18),a=n?n.toStringTag:void 0;t.exports=function(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":a&&a in Object(t)?o(t):i(t)}},function(t,e){t.exports=function(t){return null!=t&&"object"==typeof t}},function(t,e,r){!function(s){"use strict";var u={searchParams:"URLSearchParams"in self,iterable:"Symbol"in self&&"iterator"in Symbol,blob:"FileReader"in self&&"Blob"in self&&function(){try{return new Blob,!0}catch(t){return!1}}(),formData:"FormData"in self,arrayBuffer:"ArrayBuffer"in self};if(u.arrayBuffer)var e=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],r=ArrayBuffer.isView||function(t){return t&&-1 nav").offsetHeight,n=function(){var t;e.sort(function(t,e){return t.targetElement.offsetTop-e.targetElement.offsetTop}),t=e[0].targetElement.offsetTop+r>window.scrollY?0:e[e.length-1].targetElement.offsetTop+rwindow.scrollY})-1,e.forEach(function(t){return t.navElement.classList.remove("current")}),e[t].navElement.classList.add("current")};window.addEventListener("scroll",o()(n,10)),window.addEventListener("resize",o()(n,10)),n()}}()},function(t,e,r){var n=r(2);t.exports=function(){return n.Date.now()}},function(t,e,r){var n=r(1),o=r(16),i=/^\s+|\s+$/g,a=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,u=/^0o[0-7]+$/i,c=parseInt;t.exports=function(t){if("number"==typeof t)return t;if(o(t))return NaN;if(n(t)){var e="function"==typeof t.valueOf?t.valueOf():t;t=n(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=t.replace(i,"");var r=s.test(t);return r||u.test(t)?c(t.slice(2),r?2:8):a.test(t)?NaN:+t}},function(t,e,r){var n=r(3),o=r(4);t.exports=function(t){return"symbol"==typeof t||o(t)&&"[object Symbol]"==n(t)}},function(t,e,r){var n=r(6),o=Object.prototype,i=o.hasOwnProperty,a=o.toString,s=n?n.toStringTag:void 0;t.exports=function(t){var e=i.call(t,s),r=t[s];try{var n=!(t[s]=void 0)}catch(t){}var o=a.call(t);return n&&(e?t[s]=r:delete t[s]),o}},function(t,e){var r=Object.prototype.toString;t.exports=function(t){return r.call(t)}},function(t,e){!function(){var e=window.document.querySelector(".rating");if(e){function t(t){e.querySelector("#rate-star-".concat(t)).addEventListener("click",function(){!function(t){window._paq.push(["trackEvent","Docs","Rating",window.location.pathname,t])}(t),e.innerHTML="

Thank you!

"})}for(var r=1;r<=5;r++)t(r)}}()},function(t,e){var r=window.document.querySelector(".rst-content");!function(){if(r){var t=r.querySelectorAll("table");t&&0!==t.length&&t.forEach(function(t){if(!t.parentNode.classList.contains("wy-table-responsive")){var e=document.createElement("div");e.classList.add("wy-table-responsive"),t.parentNode.insertBefore(e,t),e.appendChild(t)}})}}()},function(t,e,n){"use strict";(function(t){var i=n(7);function r(t){return function(t){if(Array.isArray(t))return t}(t)||function(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}(t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function f(){var t=r(document.location.pathname.split("/")),e=t[2];return{currentVersion:t[3],currentPackageName:e,pagePath:t.slice(4).join("/")}}var a;(a=window.document.querySelectorAll(".docs-version-selector"))&&0!==a.length&&t("/_gen/packages-metadata.json").then(function(t){return t.json()}).then(function(t){var e=f().currentPackageName,r=t.find(function(t){return t["package-name"]===e});if(r){var n=r["all-versions"].sort(i.a).reverse(),o=r["stable-version"];a.forEach(function(t){return function(t,e,r){var n=t.querySelector("#version-item-template").innerText,o=document.createElement("div");function i(t,e){var r=o.cloneNode(!0),n="/docs/".concat(u,"/").concat(t,"/").concat(c);r.setAttribute("href",n),r.innerText=e,a.appendChild(r)}o.innerHTML=n,o=o.firstElementChild;var a=t.querySelector(".dropdown-menu"),s=f(),u=s.currentPackageName,c=s.pagePath;i("stable","Stable (".concat(r,")")),e.forEach(function(t){return i(t,t)})}(t,n,o)})}})}).call(this,n(5))},,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,function(t,e,r){"use strict";r.r(e);r(10),r(11),r(12),r(13),r(19),r(20),r(55),r(21)},function(t,e){Array.from(document.querySelectorAll(".toctree ul")).forEach(function(t){Array.from(t.parentNode.children).filter(function(t){return"A"===t.tagName}).forEach(function(t){var e=document.createElement("span");e.classList.add("toctree-expand"),t.insertBefore(e,t.firstChild)})})}]); \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/_sphinx_javascript_frameworks_compat.js b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/_sphinx_javascript_frameworks_compat.js new file mode 100644 index 00000000000..8549469dc29 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/_sphinx_javascript_frameworks_compat.js @@ -0,0 +1,134 @@ +/* + * _sphinx_javascript_frameworks_compat.js + * ~~~~~~~~~~ + * + * Compatability shim for jQuery and underscores.js. + * + * WILL BE REMOVED IN Sphinx 6.0 + * xref RemovedInSphinx60Warning + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/basic.css b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/basic.css new file mode 100644 index 00000000000..eeb0519a69b --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/basic.css @@ -0,0 +1,899 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} +dl.field-list > dt:after { + content: ":"; +} + + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/check-solid.svg b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/check-solid.svg new file mode 100644 index 00000000000..92fad4b5c0b --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/check-solid.svg @@ -0,0 +1,4 @@ + + + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/clipboard.min.js b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/clipboard.min.js new file mode 100644 index 00000000000..54b3c463811 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.8 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1 + + + + diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/copybutton.css b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/copybutton.css new file mode 100644 index 00000000000..f1916ec7d1b --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/copybutton.css @@ -0,0 +1,94 @@ +/* Copy buttons */ +button.copybtn { + position: absolute; + display: flex; + top: .3em; + right: .3em; + width: 1.7em; + height: 1.7em; + opacity: 0; + transition: opacity 0.3s, border .3s, background-color .3s; + user-select: none; + padding: 0; + border: none; + outline: none; + border-radius: 0.4em; + /* The colors that GitHub uses */ + border: #1b1f2426 1px solid; + background-color: #f6f8fa; + color: #57606a; +} + +button.copybtn.success { + border-color: #22863a; + color: #22863a; +} + +button.copybtn svg { + stroke: currentColor; + width: 1.5em; + height: 1.5em; + padding: 0.1em; +} + +div.highlight { + position: relative; +} + +/* Show the copybutton */ +.highlight:hover button.copybtn, button.copybtn.success { + opacity: 1; +} + +.highlight button.copybtn:hover { + background-color: rgb(235, 235, 235); +} + +.highlight button.copybtn:active { + background-color: rgb(187, 187, 187); +} + +/** + * A minimal CSS-only tooltip copied from: + * https://codepen.io/mildrenben/pen/rVBrpK + * + * To use, write HTML like the following: + * + *

Short

+ */ + .o-tooltip--left { + position: relative; + } + + .o-tooltip--left:after { + opacity: 0; + visibility: hidden; + position: absolute; + content: attr(data-tooltip); + padding: .2em; + font-size: .8em; + left: -.2em; + background: grey; + color: white; + white-space: nowrap; + z-index: 2; + border-radius: 2px; + transform: translateX(-102%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); +} + +.o-tooltip--left:hover:after { + display: block; + opacity: 1; + visibility: visible; + transform: translateX(-100%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); + transition-delay: .5s; +} + +/* By default the copy button shouldn't show up when printing a page */ +@media print { + button.copybtn { + display: none; + } +} diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/copybutton.js b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/copybutton.js new file mode 100644 index 00000000000..2ea7ff3e217 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/copybutton.js @@ -0,0 +1,248 @@ +// Localization support +const messages = { + 'en': { + 'copy': 'Copy', + 'copy_to_clipboard': 'Copy to clipboard', + 'copy_success': 'Copied!', + 'copy_failure': 'Failed to copy', + }, + 'es' : { + 'copy': 'Copiar', + 'copy_to_clipboard': 'Copiar al portapapeles', + 'copy_success': '¡Copiado!', + 'copy_failure': 'Error al copiar', + }, + 'de' : { + 'copy': 'Kopieren', + 'copy_to_clipboard': 'In die Zwischenablage kopieren', + 'copy_success': 'Kopiert!', + 'copy_failure': 'Fehler beim Kopieren', + }, + 'fr' : { + 'copy': 'Copier', + 'copy_to_clipboard': 'Copier dans le presse-papier', + 'copy_success': 'Copié !', + 'copy_failure': 'Échec de la copie', + }, + 'ru': { + 'copy': 'Скопировать', + 'copy_to_clipboard': 'Скопировать в буфер', + 'copy_success': 'Скопировано!', + 'copy_failure': 'Не удалось скопировать', + }, + 'zh-CN': { + 'copy': '复制', + 'copy_to_clipboard': '复制到剪贴板', + 'copy_success': '复制成功!', + 'copy_failure': '复制失败', + }, + 'it' : { + 'copy': 'Copiare', + 'copy_to_clipboard': 'Copiato negli appunti', + 'copy_success': 'Copiato!', + 'copy_failure': 'Errore durante la copia', + } +} + +let locale = 'en' +if( document.documentElement.lang !== undefined + && messages[document.documentElement.lang] !== undefined ) { + locale = document.documentElement.lang +} + +let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT; +if (doc_url_root == '#') { + doc_url_root = ''; +} + +/** + * SVG files for our copy buttons + */ +let iconCheck = ` + ${messages[locale]['copy_success']} + + +` + +// If the user specified their own SVG use that, otherwise use the default +let iconCopy = ``; +if (!iconCopy) { + iconCopy = ` + ${messages[locale]['copy_to_clipboard']} + + + +` +} + +/** + * Set up copy/paste for code blocks + */ + +const runWhenDOMLoaded = cb => { + if (document.readyState != 'loading') { + cb() + } else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', cb) + } else { + document.attachEvent('onreadystatechange', function() { + if (document.readyState == 'complete') cb() + }) + } +} + +const codeCellId = index => `codecell${index}` + +// Clears selected text since ClipboardJS will select the text when copying +const clearSelection = () => { + if (window.getSelection) { + window.getSelection().removeAllRanges() + } else if (document.selection) { + document.selection.empty() + } +} + +// Changes tooltip text for a moment, then changes it back +// We want the timeout of our `success` class to be a bit shorter than the +// tooltip and icon change, so that we can hide the icon before changing back. +var timeoutIcon = 2000; +var timeoutSuccessClass = 1500; + +const temporarilyChangeTooltip = (el, oldText, newText) => { + el.setAttribute('data-tooltip', newText) + el.classList.add('success') + // Remove success a little bit sooner than we change the tooltip + // So that we can use CSS to hide the copybutton first + setTimeout(() => el.classList.remove('success'), timeoutSuccessClass) + setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon) +} + +// Changes the copy button icon for two seconds, then changes it back +const temporarilyChangeIcon = (el) => { + el.innerHTML = iconCheck; + setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon) +} + +const addCopyButtonToCodeCells = () => { + // If ClipboardJS hasn't loaded, wait a bit and try again. This + // happens because we load ClipboardJS asynchronously. + if (window.ClipboardJS === undefined) { + setTimeout(addCopyButtonToCodeCells, 250) + return + } + + // Add copybuttons to all of our code cells + const COPYBUTTON_SELECTOR = 'div.highlight pre'; + const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR) + codeCells.forEach((codeCell, index) => { + const id = codeCellId(index) + codeCell.setAttribute('id', id) + + const clipboardButton = id => + `` + codeCell.insertAdjacentHTML('afterend', clipboardButton(id)) + }) + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} + + +var copyTargetText = (trigger) => { + var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); + + // get filtered text + let exclude = '.linenos'; + + let text = filterText(target, exclude); + return formatCopyText(text, '', false, true, true, true, '', '') +} + + // Initialize with a callback so we can modify the text before copy + const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText}) + + // Update UI with error/success messages + clipboard.on('success', event => { + clearSelection() + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success']) + temporarilyChangeIcon(event.trigger) + }) + + clipboard.on('error', event => { + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure']) + }) +} + +runWhenDOMLoaded(addCopyButtonToCodeCells) \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/copybutton_funcs.js b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/copybutton_funcs.js new file mode 100644 index 00000000000..dbe1aaad79c --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/copybutton_funcs.js @@ -0,0 +1,73 @@ +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +export function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/custom.css b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/custom.css new file mode 100644 index 00000000000..b1cf49f37d4 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/custom.css @@ -0,0 +1,33 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + /* + This file contains style overrides for the sphinx-design extension. + + The original defaults can be found here: + https://sphinx-design.readthedocs.io/en/alabaster-theme/css_variables.html + */ + +:root { + --sd-color-tabs-label-active: #017cee; + --sd-color-tabs-label-hover: #68d1ff; + --sd-color-tabs-underline-active: #017cee; + --sd-color-tabs-underline-hover: #68d1ff; + --sd-color-tabs-underline: transparent; +} diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css new file mode 100644 index 00000000000..eb19f698afc --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css @@ -0,0 +1 @@ +.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative}details.sd-dropdown .sd-summary-title{font-weight:700;padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary{list-style:none;padding:1em}details.sd-dropdown summary .sd-octicon.no-title{vertical-align:middle}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown summary::-webkit-details-marker{display:none}details.sd-dropdown summary:focus{outline:none}details.sd-dropdown .sd-summary-icon{margin-right:.5em}details.sd-dropdown .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary:hover .sd-summary-up svg,details.sd-dropdown summary:hover .sd-summary-down svg{opacity:1;transform:scale(1.1)}details.sd-dropdown .sd-summary-up svg,details.sd-dropdown .sd-summary-down svg{display:block;opacity:.6}details.sd-dropdown .sd-summary-up,details.sd-dropdown .sd-summary-down{pointer-events:none;position:absolute;right:1em;top:1em}details.sd-dropdown[open]>.sd-summary-title .sd-summary-down{visibility:hidden}details.sd-dropdown:not([open])>.sd-summary-title .sd-summary-up{visibility:hidden}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #0071bc;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0060a0;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem} diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/design-tabs.js b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/design-tabs.js new file mode 100644 index 00000000000..36b38cf0d91 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/design-tabs.js @@ -0,0 +1,27 @@ +var sd_labels_by_text = {}; + +function ready() { + const li = document.getElementsByClassName("sd-tab-label"); + for (const label of li) { + syncId = label.getAttribute("data-sync-id"); + if (syncId) { + label.onclick = onLabelClick; + if (!sd_labels_by_text[syncId]) { + sd_labels_by_text[syncId] = []; + } + sd_labels_by_text[syncId].push(label); + } + } +} + +function onLabelClick() { + // Activate other inputs with the same sync id. + syncId = this.getAttribute("data-sync-id"); + for (label of sd_labels_by_text[syncId]) { + if (label === this) continue; + label.previousElementSibling.checked = true; + } + window.localStorage.setItem("sphinx-design-last-tab", syncId); +} + +document.addEventListener("DOMContentLoaded", ready, false); diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/doctools.js b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/doctools.js new file mode 100644 index 00000000000..527b876ca63 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/documentation_options.js b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/documentation_options.js new file mode 100644 index 00000000000..b5932266a85 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/documentation_options.js @@ -0,0 +1,14 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '6.3.0', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/file.png b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 GIT binary patch literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( literal 0 HcmV?d00001 diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/graphviz.css b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/graphviz.css new file mode 100644 index 00000000000..19e7afd385b --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/graphviz.css @@ -0,0 +1,19 @@ +/* + * graphviz.css + * ~~~~~~~~~~~~ + * + * Sphinx stylesheet -- graphviz extension. + * + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +img.graphviz { + border: 0; + max-width: 100%; +} + +object.graphviz { + max-width: 100%; +} diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/jquery-3.6.0.js b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/jquery-3.6.0.js new file mode 100644 index 00000000000..fc6c299b73e --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/_static/jquery-3.6.0.js @@ -0,0 +1,10881 @@ +/*! + * jQuery JavaScript Library v3.6.0 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2021-03-02T17:08Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5 + // Plus for old WebKit, typeof returns "function" for HTML collections + // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756) + return typeof obj === "function" && typeof obj.nodeType !== "number" && + typeof obj.item !== "function"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.6.0", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), + function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); + } ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.6 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2021-02-16 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem && elem.namespaceURI, + docElem = elem && ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +} +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the primary Deferred + primary = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + primary.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( primary.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return primary.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject ); + } + + return primary.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + + // Support: Chrome 86+ + // In Chrome, if an element having a focusout handler is blurred by + // clicking outside of it, it invokes the handler synchronously. If + // that handler calls `.remove()` on the element, the data is cleared, + // leaving `result` undefined. We need to guard against this. + return result && result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + which: true +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + // Suppress native focus or blur as it's already being fired + // in leverageNative. + _default: function() { + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + // + // Support: Firefox 70+ + // Only Firefox includes border widths + // in computed dimensions. (gh-4529) + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate"; + tr.style.cssText = "border:1px solid"; + + // Support: Chrome 86+ + // Height set through cssText does not get applied. + // Computed height then comes back as 0. + tr.style.height = "1px"; + trChild.style.height = "9px"; + + // Support: Android 8 Chrome 86+ + // In our bodyBackground.html iframe, + // display for all div elements is set to "inline", + // which causes a problem only in Android 8 Chrome 86. + // Ensuring the div is display: block + // gets around this issue. + trChild.style.display = "block"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) + + parseInt( trStyle.borderTopWidth, 10 ) + + parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml, parserErrorElem; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) {} + + parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ]; + if ( !xml || parserErrorElem ) { + jQuery.error( "Invalid XML: " + ( + parserErrorElem ? + jQuery.map( parserErrorElem.childNodes, function( el ) { + return el.textContent; + } ).join( "\n" ) : + data + ) ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ).filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ).map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + +originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script but not if jsonp + if ( !isSuccess && + jQuery.inArray( "script", s.dataTypes ) > -1 && + jQuery.inArray( "json", s.dataTypes ) < 0 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+
+

apache-airflow-providers-databricks

+
+

Changelog

+
+

6.3.0

+
+

Features

+
    +
  • Add cancel_previous_run to DatabricksRunNowOperator (#38702)

  • +
  • add repair_run support to DatabricksRunNowOperator in deferrable mode (#38619)

  • +
  • Adds job_id as path param in update permission (#38962)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix remaining D401 checks (#37434)

  • +
  • Update ACL during job reset (#38741)

  • +
  • Remove extra slash from update permission endpoint (#38918)

  • +
  • DatabricksRunNowOperator: fix typo in latest_repair_id (#39050)

  • +
+
+
+

Misc

+
    +
  • refactor(databricks): remove redundant else block (#38397)

  • +
  • Rename 'DatabricksSqlOperator''s fields' names to comply with templated fields validation (#38052)

  • +
+
+
+
+

6.2.0

+
+

Features

+
    +
  • Update DatabricksSqlOperator to work with namedtuple (#37025)

  • +
+
+
+

Misc

+
    +
  • Bump aiohttp min version to avoid CVE-2024-23829 and CVE-2024-23334 (#37110)

  • +
  • feat: Switch all class, functions, methods deprecations to decorators (#36876)

  • +
  • Get rid of pytest-httpx as dependency (#37334)

  • +
+
+
+
+

6.1.0

+
+

Features

+
    +
  • [FEAT] adds repair run functionality for databricks (#36601)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix databricks_sql hook query failing on empty result for return_tuple (#36827)

  • +
  • Rename columns to valid namedtuple attributes + ensure Row.fields are retrieved as tuple (#36949)

  • +
  • check status before DatabricksSubmitRunOperator & DatabricksSubmitRunOperator executes in deferrable mode (#36862)

  • +
+
+
+
+

6.0.0

+
+

Note

+

This release of provider is only available for Airflow 2.6+ as explained in the +Apache Airflow providers support policy.

+
+
+

Breaking changes

+
    +
  • Return common data structure in DBApi derived classes (#36205)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix: Implement support for 'fetchone()' in the ODBCHook and the Databricks SQL Hook (#36161)

  • +
+
+
+

Misc

+
    +
  • Bump minimum Airflow version in providers to Airflow 2.6.0 (#36017)

  • +
  • fix typos in DatabricksSubmitRunOperator (#36248)

  • +
  • Add code snippet formatting in docstrings via Ruff (#36262)

  • +
+
+
+
+

5.0.1 (YANKED)

+
+

Warning

+

This release has been yanked with a reason: The provider DBApiHook output returned broken output.

+
+
+

Misc

+
    +
  • Make pyodbc.Row and databricks.Row JSON-serializable via new 'make_serializable' method (#32319)

  • +
+
+
+
+

5.0.0

+
+

Breaking changes

+

The offset parameter has been deprecated from list_jobs in favor of faster pagination with page_token similarly to Databricks API.

+
    +
  • Remove offset-based pagination from 'list_jobs' function in 'DatabricksHook' (#34926)

  • +
+
+
+
+

4.7.0

+
+

Features

+
    +
  • Add operator to create jobs in Databricks (#35156)

  • +
+
+
+
+

4.6.0

+
+

Note

+

This release of provider is only available for Airflow 2.5+ as explained in the +Apache Airflow providers support policy.

+
+
+

Features

+
    +
  • Add 'DatabricksHook' ClusterState (#34643)

  • +
+
+
+

Bug Fixes

+
    +
  • Respect 'soft_fail' parameter in 'DatabricksSqlSensor' (#34544)

  • +
  • Respect 'soft_fail' argument when running DatabricksPartitionSensor (#34517)

  • +
  • Decode response in f-string (#34518)

  • +
+
+
+

Misc

+
    +
  • Bump min airflow version of providers (#34728)

  • +
  • Use aiohttp.BasicAuth instead of HTTPBasicAuth for aiohttp session in databricks hook (#34590)

  • +
  • Update 'list_jobs' function in 'DatabricksHook' to token-based pagination  (#33472)

  • +
+
+
+
+

4.5.0

+
+

Features

+
    +
  • Add "QUEUED" to RUN_LIFE_CYCLE_STATES following deployement of (#33886)

  • +
  • allow DatabricksSubmitRunOperator to accept a pipeline name for a pipeline_task (#32903)

  • +
+
+
+

Misc

+
    +
  • Replace sequence concatenation by unpacking in Airflow providers (#33933)

  • +
  • Improve modules import in Airflow providers by some of them into a type-checking block (#33754)

  • +
  • Use literal dict instead of calling dict() in providers (#33761)

  • +
  • Use f-string instead of  in Airflow providers (#33752)

  • +
+
+
+
+

4.4.0

+
+

Note

+

This release excluded databricks-sql-connector version 2.9.0 due to a bug that it does not properly declare urllib3 +for more information please see https://github.com/databricks/databricks-sql-python/issues/190

+
+
+

Features

+
    +
  • Add Service Principal OAuth for Databricks. (#33005)

  • +
+
+
+

Misc

+
    +
  • Update docs in databricks.py - we use 2.1 now (#32340)

  • +
  • Do not create lists we don't need (#33519)

  • +
  • Refactor: Improve detection of duplicates and list sorting (#33675)

  • +
  • Simplify conditions on len() in other providers (#33569)

  • +
  • Refactor: Simplify code in smaller providers (#33234)

  • +
+
+
+
+

4.3.3

+
+

Misc

+
    +
  • Add a new parameter to SQL operators to specify conn id field (#30784)

  • +
+
+
+
+

4.3.2

+
+

Bug Fixes

+
    +
  • fix(providers/databricks): remove the execute method from to-be-deprecated DatabricksRunNowDeferrableOperator (#32806)

  • +
+
+
+

Misc

+
    +
  • Add missing execute_complete method for 'DatabricksRunNowOperator' (#32689)

  • +
  • Add more accurate typing for DbApiHook.run method (#31846)

  • +
+
+
+
+

4.3.1

+
+

Bug Fixes

+
    +
  • Modify 'template_fields' of 'DatabricksSqlOperator' to support parent class fields (#32253)

  • +
+
+
+

Misc

+
    +
  • Add default_deferrable config (#31712)

  • +
+
+
+
+

4.3.0

+
+

Note

+

This release dropped support for Python 3.7

+
+
+

Features

+
    +
  • add a return when the event is yielded in a loop to stop the execution (#31985)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix type annotation (#31888)

  • +
  • Fix Databricks SQL operator serialization (#31780)

  • +
  • Making Databricks run related multi-query string in one session again (#31898) (#31899)

  • +
+
+
+

Misc

+
    +
  • Remove return statement after yield from triggers class (#31703)

  • +
  • Remove Python 3.7 support (#30963)

  • +
+
+
+
+

4.2.0

+
+

Note

+

This release of provider is only available for Airflow 2.4+ as explained in the +Apache Airflow providers support policy.

+
+
+

Features

+
    +
  • Add conditional output processing in SQL operators (#31136)

  • +
  • Add cancel all runs functionality to Databricks hook (#31038)

  • +
  • Add retry param in databrics async operator (#30744)

  • +
  • Add repair job functionality to databricks hook (#30786)

  • +
  • Add 'DatabricksPartitionSensor' (#30980)

  • +
+
+
+

Misc

+
    +
  • Bump minimum Airflow version in providers (#30917)

  • +
  • Deprecate databricks async operator (#30761)

  • +
+
+
+
+

4.1.0

+
+

Features

+
    +
  • Add delete inactive run functionality to databricks provider (#30646)

  • +
  • Databricks SQL sensor (#30477)

  • +
+
+
+
+

4.0.1

+
+

Bug Fixes

+
    +
  • DatabricksSubmitRunOperator to support taskflow (#29840)

  • +
+
+
+
+

4.0.0

+
+

Breaking changes

+

The DatabricksSqlHook is now conforming to the same semantics as all the other DBApiHook +implementations and returns the same kind of response in its run method. Previously (pre 4.* versions +of the provider, the Hook returned Tuple of ("cursor description", "results") which was not compatible +with other DBApiHooks that return just "results". After this change (and dependency on common.sql >= 1.3.1), +The DatabricksSqlHook returns now "results" only. The description can be retrieved via +last_description field of the hook after run method completes.

+

That makes the DatabricksSqlHook suitable for generic SQL operator and detailed lineage analysis.

+

If you had custom hooks or used the Hook in your TaskFlow code or custom operators that relied on this +behaviour, you need to adapt your DAGs.

+

The Databricks DatabricksSQLOperator is also more standard and derives from common +SQLExecuteQueryOperator and uses more consistent approach to process output when SQL queries are run. +However in this case the result returned by execute method is unchanged (it still returns Tuple of +("description", "results") and this Tuple is pushed to XCom, so your DAGs relying on this behaviour +should continue working without any change.

+
    +
  • Fix errors in Databricks SQL operator introduced when refactoring (#27854)

  • +
  • Bump common.sql provider to 1.3.1 (#27888)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix templating fields and do_xcom_push in DatabricksSQLOperator (#27868)

  • +
  • Fixing the behaviours of SQL Hooks and Operators finally (#27912)

  • +
+
+
+
+

3.4.0 (YANKED)

+
+

Warning

+

This release has been yanked with a reason: There is a bug in DatabricsksSQLOperator

+
+
+

Note

+

This release of provider is only available for Airflow 2.3+ as explained in the +Apache Airflow providers support policy.

+
+
+

Misc

+
    +
  • Move min airflow version to 2.3.0 for all providers (#27196)

  • +
  • Replace urlparse with urlsplit (#27389)

  • +
+
+
+

Features

+
    +
  • Add SQLExecuteQueryOperator (#25717)

  • +
  • Use new job search API for triggering Databricks job by name (#27446)

  • +
+
+
+
+

3.3.0

+
+

Features

+
    +
  • DatabricksSubmitRunOperator dbt task support (#25623)

  • +
+
+
+

Misc

+
    +
  • Add common-sql lower bound for common-sql (#25789)

  • +
  • Remove duplicated connection-type within the provider (#26628)

  • +
+
+
+

Bug Fixes

+
    +
  • Databricks: fix provider name in the User-Agent string (#25873)

  • +
+
+
+
+

3.2.0

+
+

Features

+
    +
  • Databricks: update user-agent string (#25578)

  • +
  • More improvements in the Databricks operators (#25260)

  • +
  • Improved telemetry for Databricks provider (#25115)

  • +
  • Unify DbApiHook.run() method with the methods which override it (#23971)

  • +
+
+
+

Bug Fixes

+
    +
  • Databricks: fix test_connection implementation (#25114)

  • +
  • Do not convert boolean values to string in deep_string_coerce function (#25394)

  • +
  • Correctly handle output of the failed tasks (#25427)

  • +
  • Databricks: Fix provider for Airflow 2.2.x (#25674)

  • +
+
+
+
+

3.1.0

+
+

Features

+
    +
  • Added databricks_conn_id as templated field (#24945)

  • +
  • Add 'test_connection' method to Databricks hook (#24617)

  • +
  • Move all SQL classes to common-sql provider (#24836)

  • +
+
+
+

Bug Fixes

+
    +
  • Update providers to use functools compat for ''cached_property'' (#24582)

  • +
+
+
+
+

3.0.0

+
+

Breaking changes

+
+

Note

+

This release of provider is only available for Airflow 2.2+ as explained in the +Apache Airflow providers support policy.

+
+
+
+

Features

+
    +
  • Add Deferrable Databricks operators (#19736)

  • +
  • Add git_source to DatabricksSubmitRunOperator (#23620)

  • +
+
+
+

Bug Fixes

+
    +
  • fix: DatabricksSubmitRunOperator and DatabricksRunNowOperator cannot define .json as template_ext (#23622) (#23641)

  • +
  • Fix UnboundLocalError when sql is empty list in DatabricksSqlHook (#23815)

  • +
+
+
+
+

2.7.0

+
+

Features

+
    +
  • Update to the released version of DBSQL connector

  • +
  • DatabricksSqlOperator - switch to databricks-sql-connector 2.x

  • +
  • Further improvement of Databricks Jobs operators (#23199)

  • +
+
+
+
+

2.6.0

+
+

Features

+
    +
  • More operators for Databricks Repos (#22422)

  • +
  • Add a link to Databricks Job Run (#22541)

  • +
  • Databricks SQL operators are now Python 3.10 compatible (#22886)

  • +
+
+
+

Bug Fixes

+
    +
  • Databricks: Correctly handle HTTP exception (#22885)

  • +
+
+
+

Misc

+
    +
  • Refactor 'DatabricksJobRunLink' to not create ad hoc TaskInstances (#22571)

  • +
+
+
+
+

2.5.0

+
+

Features

+
    +
  • Operator for updating Databricks Repos (#22278)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix mistakenly added install_requires for all providers (#22382)

  • +
+
+
+
+

2.4.0

+
+

Features

+
    +
  • Add new options to DatabricksCopyIntoOperator (#22076)

  • +
  • Databricks hook - retry on HTTP Status 429 as well (#21852)

  • +
+
+
+

Misc

+
    +
  • Skip some tests for Databricks from running on Python 3.10 (#22221)

  • +
+
+
+
+

2.3.0

+
+

Features

+
    +
  • Add-showing-runtime-error-feature-to-DatabricksSubmitRunOperator (#21709)

  • +
  • Databricks: add support for triggering jobs by name (#21663)

  • +
  • Added template_ext = ('.json') to databricks operators #18925 (#21530)

  • +
  • Databricks SQL operators (#21363)

  • +
+
+
+

Bug Fixes

+
    +
  • Fixed changelog for January 2022 (delayed) provider's release (#21439)

  • +
+
+
+

Misc

+
    +
  • Support for Python 3.10

  • +
  • Updated Databricks docs for correct jobs 2.1 API and links (#21494)

  • +
+
+
+
+

2.2.0

+
+

Features

+
    +
  • Add 'wait_for_termination' argument for Databricks Operators (#20536)

  • +
  • Update connection object to ''cached_property'' in ''DatabricksHook'' (#20526)

  • +
  • Remove 'host' as an instance attr in 'DatabricksHook' (#20540)

  • +
  • Databricks: fix verification of Managed Identity (#20550)

  • +
+
+
+
+

2.1.0

+
+

Features

+
    +
  • Databricks: add more methods to represent run state information (#19723)

  • +
  • Databricks - allow Azure SP authentication on other Azure clouds (#19722)

  • +
  • Databricks: allow to specify PAT in Password field (#19585)

  • +
  • Databricks jobs 2.1 (#19544)

  • +
  • Update Databricks API from 2.0 to 2.1 (#19412)

  • +
  • Authentication with AAD tokens in Databricks provider (#19335)

  • +
  • Update Databricks operators to match latest version of API 2.0 (#19443)

  • +
  • Remove db call from DatabricksHook.__init__() (#20180)

  • +
+
+
+

Bug Fixes

+
    +
  • Fixup string concatenations (#19099)

  • +
  • Databricks hook: fix expiration time check (#20036)

  • +
+
+
+
+

2.0.2

+
+

Bug Fixes

+
+
    +
  • Move DB call out of DatabricksHook.__init__ (#18339)

  • +
+
+
+
+
+

2.0.1

+
+

Misc

+
    +
  • Optimise connection importing for Airflow 2.2.0

  • +
+
+
+
+

2.0.0

+
+

Breaking changes

+
    +
  • Auto-apply apply_default decorator (#15667)

  • +
+
+

Warning

+

Due to apply_default decorator removal, this version of the provider requires Airflow 2.1.0+. +If your Airflow version is < 2.1.0, and you want to install this provider version, first upgrade +Airflow to at least version 2.1.0. Otherwise your Airflow package version will be upgraded +automatically and you will have to manually run airflow upgrade db to complete the migration.

+
+
+
+
+

1.0.1

+

Updated documentation and readme files.

+
+
+

1.0.0

+

Initial version of the provider.

+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/commits.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/commits.html new file mode 100644 index 00000000000..ef22f4c2c7e --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/commits.html @@ -0,0 +1,2813 @@ + + + + + + + + + + + + Package apache-airflow-providers-databricks — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

Package apache-airflow-providers-databricks

+

Databricks

+

This is detailed commit list of changes for versions provider package: databricks. +For high-level changelog, see package information including changelog.

+
+

6.3.0

+

Latest change: 2024-04-16

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

66df296a6e

2024-04-16

[FIX] typo in parameter (#39050)

629545bea2

2024-04-14

Adds job_id as path param in update permission (#38962)

f9dcc82fb6

2024-04-13

Prepare docs 1st wave (RC2) April 2024 (#38995)

4a669fb1a9

2024-04-11

Remove extra slash from update permission endpoint (#38918)

5fa80b6aea

2024-04-10

Prepare docs 1st wave (RC1) April 2024 (#38863)

6f21f7dc9b

2024-04-10

Update ACL during job reset (#38741)

4e6d3fa4cf

2024-04-08

Add cancel_previous_run to DatabricksRunNowOperator (#38702)

39b684d91a

2024-04-01

add repair_run support to DatabricksRunNowOperator in deferrable mode (#38619)

c74947a69d

2024-03-22

refactor(databricks): remove redundant else block (#38397)

b5b972a106

2024-03-18

Update yanked versions in providers changelogs (#38262)

0a74928894

2024-03-18

Bump ruff to 0.3.3 (#38240)

aa75fbb2b8

2024-03-16

Restore Python 3.12 support for Databricks (#38207)

4742fc0ea5

2024-03-15

Rename 'DatabricksSqlOperator''s fields' names to comply with templated fields validation (#38052)

8fc984873a

2024-03-12

Exclude Python 3.12 for Databricks provider (#38070)

83316b8158

2024-03-04

Prepare docs 1st wave (RC1) March 2024 (#37876)

14d9bff3ad

2024-02-24

update pre-commit (#37665)

5a0be392e6

2024-02-16

Add comment about versions updated by release manager (#37488)

e346253760

2024-02-15

Fix remaining D401 checks (#37434)

+
+
+

6.2.0

+

Latest change: 2024-02-12

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

bfb054e9e8

2024-02-12

Prepare docs 1st wave of Providers February 2024 (#37326)

78294c24e2

2024-02-11

Get rid of pytest-httpx as dependency (#37334)

0c4210af62

2024-01-31

Bump aiohttp min version to avoid CVE-2024-23829 and CVE-2024-23334 (#37110)

6d748c923b

2024-01-30

Update DatabricksSqlOperator to work with namedtuple (#37025)

dec2662190

2024-01-30

feat: Switch all class, functions, methods deprecations to decorators (#36876)

+
+
+

6.1.0

+

Latest change: 2024-01-26

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

cead3da4a6

2024-01-26

Add docs for RC2 wave of providers for 2nd round of Jan 2024 (#37019)

0b680c9492

2024-01-26

Revert "Provide the logger_name param in providers hooks in order to override the logger name (#36675)" (#37015)

c0f7601391

2024-01-23

Rename columns to valid namedtuple attributes + ensure Row.fields are retrieved as tuple (#36949)

347373986c

2024-01-23

check status before DatabricksSubmitRunOperator & DatabricksSubmitRunOperator executes in deferrable mode (#36862)

2b4da0101f

2024-01-22

Prepare docs 2nd wave of Providers January 2024 (#36945)

13b0930bf4

2024-01-17

Fix databricks_sql hook query failing on empty result for return_tuple (#36827)

574102fd29

2024-01-11

[FEAT] adds repair run functionality for databricks (#36601)

c439ab87c4

2024-01-10

Standardize airflow build process and switch to Hatchling build backend (#36537)

6bd450da1e

2024-01-10

Provide the logger_name param in providers hooks in order to override the logger name (#36675)

f7b663d9af

2024-01-07

Run mypy checks for full packages in CI (#36638)

19ebcac239

2024-01-07

Prepare docs 1st wave of Providers January 2024 (#36640)

6937ae7647

2023-12-30

Speed up autocompletion of Breeze by simplifying provider state (#36499)

+
+
+

6.0.0

+

Latest change: 2023-12-23

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

77b563bfc5

2023-12-23

Update version and added breaking change for databricks provider (#36382)

b15d5578da

2023-12-23

Re-apply updated version numbers to 2nd wave of providers in December (#36380)

f5883d6e7b

2023-12-23

Prepare 2nd wave of providers in December (#36373)

5fe5d31a46

2023-12-22

Return common data structure in DBApi derived classes

322aa649ed

2023-12-21

fix typos in DatabricksSubmitRunOperator (#36248)

e9ba37bb58

2023-12-17

Add code snippet formatting in docstrings via Ruff (#36262)

64931b1a65

2023-12-12

Prepare docs 1st wave of Providers December 2023 RC2 (#36190)

36010f6d0e

2023-12-11

Fix: Implement support for 'fetchone()' in the ODBCHook and the Databricks SQL Hook (#36161)

999b70178a

2023-12-08

Prepare docs 1st wave of Providers December 2023 (#36112)

d0918d77ee

2023-12-07

Bump minimum Airflow version in providers to Airflow 2.6.0 (#36017)

+
+
+

5.0.1

+

Latest change: 2023-11-24

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

0b23d5601c

2023-11-24

Prepare docs 2nd wave of Providers November 2023 (#35836)

99534e47f3

2023-11-19

Use reproducible builds for provider packages (#35693)

064fc2b775

2023-11-17

Make pyodbc.Row and databricks.Row JSON-serializable via new 'make_serializable' method (#32319)

99df205f42

2023-11-16

Fix and reapply templates for provider documentation (#35686)

+
+
+

5.0.0

+

Latest change: 2023-11-08

+ +++++ + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

1b059c57d6

2023-11-08

Prepare docs 1st wave of Providers November 2023 (#35537)

10bac853d2

2023-11-03

Remove offset-based pagination from 'list_jobs' function in 'DatabricksHook' (#34926)

+
+
+

4.7.0

+

Latest change: 2023-10-28

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

d1c58d86de

2023-10-28

Prepare docs 3rd wave of Providers October 2023 - FIX (#35233)

3592ff4046

2023-10-28

Prepare docs 3rd wave of Providers October 2023 (#35187)

a8784e3c35

2023-10-28

Add operator to create jobs in Databricks (#35156)

dd7ba3cae1

2023-10-19

Pre-upgrade 'ruff==0.0.292' changes in providers (#35053)

7a93b19138

2023-10-16

D401 Support - Providers: DaskExecutor to Github (Inclusive) (#34935)

+
+
+

4.6.0

+

Latest change: 2023-10-13

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

e9987d5059

2023-10-13

Prepare docs 1st wave of Providers in October 2023 (#34916)

946b539f0d

2023-10-12

Add 'DatabricksHook' ClusterState (#34643)

0c8e30e43b

2023-10-05

Bump min airflow version of providers (#34728)

7ebf4220c9

2023-09-28

Refactor usage of str() in providers (#34320)

a1ef232230

2023-09-25

Use aiohttp.BasicAuth instead of HTTPBasicAuth for aiohttp session in databricks hook (#34590)

f26fa6d602

2023-09-22

Respect 'soft_fail' parameter in 'DatabricksSqlSensor' (#34544)

3813ed69c7

2023-09-22

Respect 'soft_fail' argument when running DatabricksPartitionSensor (#34517)

966c2bce9f

2023-09-21

Decode response in f-string (#34518)

dfec053371

2023-09-12

Update 'list_jobs' function in 'DatabricksHook' to token-based pagination  (#33472)

+
+
+

4.5.0

+

Latest change: 2023-09-08

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

21990ed894

2023-09-08

Prepare docs for 09 2023 - 1st wave of Providers (#34201)

c45617c4d5

2023-09-07

allow DatabricksSubmitRunOperator to accept a pipeline name for a pipeline_task (#32903)

55976af32e

2023-08-31

Replace sequence concatination by unpacking in Airflow providers (#33933)

f7a005db8c

2023-08-30

Add "QUEUED" to RUN_LIFE_CYCLE_STATES following deployement of (#33886)

9d8c77e447

2023-08-27

Improve modules import in Airflow providers by some of them into a type-checking block (#33754)

b11525702c

2023-08-26

Use literal dict instead of calling dict() in providers (#33761)

c90eec9365

2023-08-26

Use f-string instead of  in Airflow providers (#33752)

+
+
+

4.4.0

+

Latest change: 2023-08-26

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

c077d19060

2023-08-26

Prepare docs for Aug 2023 3rd wave of Providers (#33730)

dc47c460dc

2023-08-24

Update docs in databricks.py - we use 2.1 now (#32340)

4154cc04ce

2023-08-24

Do not create lists we don't need (#33519)

2dbb963324

2023-08-24

Refactor: Improve detection of duplicates and list sorting (#33675)

1cdd82391e

2023-08-21

Simplify conditions on len() in other providers (#33569)

a91ee7ac2f

2023-08-20

Refactor: Simplify code in smaller providers (#33234)

8bf53dd554

2023-08-14

Add Service Principal OAuth for Databricks. (#33005)

5f8f25b34c

2023-08-11

Ecldude databrick connector 2.9.0 due to a bug (#33311)

+
+
+

4.3.3

+

Latest change: 2023-08-11

+ +++++ + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

b5a4d36383

2023-08-11

Prepare docs for Aug 2023 2nd wave of Providers (#33291)

9736143468

2023-08-07

Add a new parameter to SQL operators to specify conn id field (#30784)

+
+
+

4.3.2

+

Latest change: 2023-07-29

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

d06b7af69a

2023-07-29

Prepare docs for July 2023 3rd wave of Providers (#32875)

58e21c66fd

2023-07-25

fix(providers/databricks): remove the execute method from to-be-deprecated DatabricksRunNowDeferrableOperator (#32806)

6313e52932

2023-07-24

Add missing execute_complete method for 'DatabricksRunNowOperator' (#32689)

60c49ab2df

2023-07-19

Add more accurate typing for DbApiHook.run method (#31846)

+
+
+

4.3.1

+

Latest change: 2023-07-06

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

225e3041d2

2023-07-06

Prepare docs for July 2023 wave of Providers (RC2) (#32381)

3878fe6fab

2023-07-05

Remove spurious headers for provider changelogs (#32373)

cb4927a018

2023-07-05

Prepare docs for July 2023 wave of Providers (#32298)

f8593503cb

2023-07-05

Add default_deferrable config (#31712)

6b4350e89c

2023-06-29

Modify 'template_fields' of 'DatabricksSqlOperator' to support parent class fields (#32253)

d1aa509bbd

2023-06-28

D205 Support - Providers: Databricks to Github (inclusive) (#32243)

09d4718d3a

2023-06-27

Improve provider documentation and README structure (#32125)

+
+
+

4.3.0

+

Latest change: 2023-06-20

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

79bcc2e668

2023-06-20

Prepare RC1 docs for June 2023 wave of Providers (#32001)

8b146152d6

2023-06-20

Add note about dropping Python 3.7 for providers (#32015)

69bc90b824

2023-06-19

Fix type annotation (#31888)

66299338eb

2023-06-18

add a return when the event is yielded in a loop to stop the execution (#31985)

7b096483fa

2023-06-14

Making Databricks run related multi-query string in one session again (#31898) (#31899)

049c6184b7

2023-06-08

Fix Databricks SQL operator serialization (#31780)

9276310a43

2023-06-05

Improve docstrings in providers (#31681)

86b5ba2802

2023-06-04

Remove return statement after yield from triggers class (#31703)

dc5bf3fd02

2023-06-02

Add discoverability for triggers in provider.yaml (#31576)

a59076eaee

2023-06-02

Add D400 pydocstyle check - Providers (#31427)

9fa75aaf7a

2023-05-29

Remove Python 3.7 support (#30963)

+
+
+

4.2.0

+

Latest change: 2023-05-19

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

45548b9451

2023-05-19

Prepare RC2 docs for May 2023 wave of Providers (#31416)

abea189022

2023-05-18

Use '__version__' in providers not 'version' (#31393)

f5aed58d9f

2023-05-18

Fixing circular import error in providers caused by airflow version check (#31379)

d9ff55cf6d

2023-05-16

Prepare docs for May 2023 wave of Providers (#31252)

fdc7a31aeb

2023-05-13

Add 'DatabricksPartitionSensor' (#30980)

edd7133a13

2023-05-09

Add conditional output processing in SQL operators (#31136)

3df0be0f6f

2023-05-08

Add cancel all runs functionality to Databricks hook (#31038)

ac46902154

2023-05-04

Move TaskInstanceKey to a separate file (#31033)

0a30706aa7

2023-05-03

Use 'AirflowProviderDeprecationWarning' in providers (#30975)

eef5bc7f16

2023-05-03

Add full automation for min Airflow version for providers (#30994)

a7eb32a5b2

2023-04-30

Bump minimum Airflow version in providers (#30917)

9409446097

2023-04-24

Add cli cmd to list the provider trigger info (#30822)

ecb9a9ea78

2023-04-23

Add retry param in databrics async operator (#30744)

9bebf85e24

2023-04-22

Add repair job functionality to databricks hook (#30786)

7d02277ae1

2023-04-22

Deprecate databricks async operator (#30761)

+
+
+

4.1.0

+

Latest change: 2023-04-21

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

e46ce78b66

2023-04-21

Prepare docs for adhoc release of providers (#30787)

37cf0506b5

2023-04-14

Add delete inactive run functionality to databricks provider (#30646)

1e311cf036

2023-04-11

Databricks SQL sensor (#30477)

d23a3bbed8

2023-04-04

Add mechanism to suspend providers (#30422)

+
+
+

4.0.1

+

Latest change: 2023-04-02

+ +++++ + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

55dbf1ff1f

2023-04-02

Prepare docs for April 2023 wave of Providers (#30378)

c3867781e0

2023-03-08

adding trigger info to provider yaml (#29950)

c405ecb63e

2023-03-07

DatabricksSubmitRunOperator to support taskflow (#29840)

+
+
+

4.0.0

+

Latest change: 2022-11-26

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

25bdbc8e67

2022-11-26

Updated docs for RC3 wave of providers (#27937)

db5375bea7

2022-11-26

Fixing the behaviours of SQL Hooks and Operators finally (#27912)

2e20e9f7eb

2022-11-24

Prepare for follow-up relase for November providers (#27774)

80c327bd3b

2022-11-24

Bump common.sql provider to 1.3.1 (#27888)

ea306c9462

2022-11-24

Fix errors in Databricks SQL operator introduced when refactoring (#27854)

a343bba1e3

2022-11-23

Fix templating fields and do_xcom_push in DatabricksSQLOperator (#27868)

+
+
+

3.4.0

+

Latest change: 2022-11-15

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

12c3c39d1a

2022-11-15

pRepare docs for November 2022 wave of Providers (#27613)

00af5c007e

2022-11-14

Replace urlparse with urlsplit (#27389)

eb06c65556

2022-11-11

Use new job search API for triggering Databricks job by name (#27446)

9ab1a6a3e7

2022-10-27

Update old style typing (#26872)

78b8ea2f22

2022-10-24

Move min airflow version to 2.3.0 for all providers (#27196)

2a34dc9e84

2022-10-23

Enable string normalization in python formatting - providers (#27205)

ecd4d6654f

2022-10-18

Add SQLExecuteQueryOperator (#25717)

+
+
+

3.3.0

+

Latest change: 2022-09-28

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

f8db64c35c

2022-09-28

Update docs for September Provider's release (#26731)

89e44c46ad

2022-09-27

Remove duplicated connection-type within the provider (#26628)

06acf40a43

2022-09-13

Apply PEP-563 (Postponed Evaluation of Annotations) to non-core airflow (#26289)

5066844513

2022-09-09

D400 first line should end with period batch02 (#25268)

25a9c6a905

2022-08-26

DatabricksSubmitRunOperator dbt task support (#25623)

9535ec0bba

2022-08-22

Databricks: fix provider name in the User-Agent string (#25873)

ca9229b6fe

2022-08-18

Add common-sql lower bound for common-sql (#25789)

+
+
+

3.2.0

+

Latest change: 2022-08-15

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

7d0525a55b

2022-08-15

Prepare documentation for RC4 release of providers (#25720)

4d32f61fd0

2022-08-12

Databricks: Fix provider for Airflow 2.2.x (#25674)

e5ac6c7cfb

2022-08-10

Prepare docs for new providers release (August 2022) (#25618)

52f2f5bfa8

2022-08-07

Databricks: update user-agent string (#25578)

0255a0a5e7

2022-08-04

Do not convert boolean values to string in deep_string_coerce function (#25394)

679a85325a

2022-08-03

Correctly handle output of the failed tasks (#25427)

82f842ffc5

2022-07-28

updated documentation for databricks operator (#24599)

54a8c4fd2a

2022-07-27

More improvements in the Databricks operators (#25260)

7438707747

2022-07-26

Improved telemetry for Databricks provider (#25115)

df00436569

2022-07-22

Unify DbApiHook.run() method with the methods which override it (#23971)

2f70daf5ac

2022-07-18

Databricks: fix test_connection implementation (#25114)

+
+
+

3.1.0

+

Latest change: 2022-07-13

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

d2459a241b

2022-07-13

Add documentation for July 2022 Provider's release (#25030)

8dfe7bf5ff

2022-07-11

Added databricks_conn_id as templated field (#24945)

acaa0635c8

2022-07-08

Automatically detect if non-lazy logging interpolation is used (#24910)

46bbfdade0

2022-07-07

Move all SQL classes to common-sql provider (#24836)

96b01a8012

2022-07-05

Remove "bad characters" from our codebase (#24841)

0de31bd73a

2022-06-29

Move provider dependencies to inside provider folders (#24672)

510a6bab45

2022-06-28

Remove 'hook-class-names' from provider.yaml (#24702)

ed37c3a0e8

2022-06-28

Add 'test_connection' method to Databricks hook (#24617)

9c59831ee7

2022-06-21

Update providers to use functools compat for ''cached_property'' (#24582)

+
+
+

3.0.0

+

Latest change: 2022-06-09

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

dcdcf3a2b8

2022-06-09

Update release notes for RC2 release of Providers for May 2022 (#24307)

717a7588bc

2022-06-07

Update package description to remove double min-airflow specification (#24292)

aeabe994b3

2022-06-07

Prepare docs for May 2022 provider's release (#24231)

027b707d21

2022-06-05

Add explanatory note for contributors about updating Changelog (#24229)

ddf9013098

2022-06-05

AIP-47 - Migrate databricks DAGs to new design #22442 (#24203)

acf89510cd

2022-06-04

fix: DatabricksSubmitRunOperator and DatabricksRunNowOperator cannot define .json as template_ext (#23622) (#23641)

92ddcf4ac6

2022-05-27

Introduce 'flake8-implicit-str-concat' plugin to static checks (#23873)

6150d28323

2022-05-22

Add Deferrable Databricks operators (#19736)

cf5a78e91c

2022-05-22

Fix UnboundLocalError when sql is empty list in DatabricksSqlHook (#23815)

d0a5b3a4f2

2022-05-13

Add git_source to DatabricksSubmitRunOperator (#23620)

+
+
+

2.7.0

+

Latest change: 2022-05-12

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

75c60923e0

2022-05-12

Prepare provider documentation 2022.05.11 (#23631)

428a439953

2022-05-09

Clean up in-line f-string concatenation (#23591)

a58506b2a6

2022-04-26

Address review comments

6a3d6cc32b

2022-04-26

Update to the released version of DBSQL connector

7b3bf4e435

2022-04-26

DatabricksSqlOperator - switch to databricks-sql-connector 2.x

f02b0b6b40

2022-04-25

Further improvement of Databricks Jobs operators (#23199)

8b6b0848a3

2022-04-23

Use new Breese for building, pulling and verifying the images. (#23104)

+
+
+

2.6.0

+

Latest change: 2022-04-13

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

40831144be

2022-04-13

Prepare for RC2 release of March Databricks provider (#22979)

7be57eb256

2022-04-10

Databricks SQL operators are now Python 3.10 compatible (#22886)

aa8c08db38

2022-04-10

Databricks: Correctly handle HTTP exception (#22885)

6933022e94

2022-04-10

Fix new MyPy errors in main (#22884)

56ab82ed7a

2022-04-07

Prepare mid-April provider documentation. (#22819)

1b12c93ed3

2022-03-31

Refactor 'DatabricksJobRunLink' to not create ad hoc TaskInstances (#22571)

95169d1d07

2022-03-27

Add a link to Databricks Job Run (#22541)

352d7f72dd

2022-03-27

More operators for Databricks Repos (#22422)

c063fc688c

2022-03-25

Update black precommit (#22521)

+
+
+

2.5.0

+

Latest change: 2022-03-22

+ +++++ + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

d7dbfb7e26

2022-03-22

Add documentation for bugfix release of Providers (#22383)

cc920963a6

2022-03-15

Operator for updating Databricks Repos (#22278)

+
+
+

2.4.0

+

Latest change: 2022-03-14

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

16adc035b1

2022-03-14

Add documentation for Classifier release for March 2022 (#22226)

12e9e2c695

2022-03-14

Databricks hook - retry on HTTP Status 429 as well (#21852)

af9d85ccd8

2022-03-13

Skip some tests for Databricks from running on Python 3.10 (#22221)

4014194320

2022-03-08

Add new options to DatabricksCopyIntoOperator (#22076)

+
+
+

2.3.0

+

Latest change: 2022-03-07

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

f5b96315fe

2022-03-07

Add documentation for Feb Providers release (#22056)

62bf1276f6

2022-03-01

Add-showing-runtime-error-feature-to-DatabricksSubmitRunOperator (#21709)

27d19e7626

2022-02-27

Databricks SQL operators (#21363)

a1845c68f9

2022-02-26

Databricks: add support for triggering jobs by name (#21663)

7cca82495b

2022-02-15

Updated Databricks docs for correct jobs 2.1 API and links (#21494)

0a2d0d1ecb

2022-02-12

Added template_ext = ('.json') to databricks operators #18925 (#21530)

d94fa37830

2022-02-08

Fixed changelog for January 2022 (delayed) provider's release (#21439)

6c3a67d4fc

2022-02-05

Add documentation for January 2021 providers release (#21257)

602abe8394

2022-01-20

Remove ':type' lines now sphinx-autoapi supports typehints (#20951)

+
+
+

2.2.0

+

Latest change: 2021-12-31

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

f77417eb0d

2021-12-31

Fix K8S changelog to be PyPI-compatible (#20614)

97496ba2b4

2021-12-31

Update documentation for provider December 2021 release (#20523)

0bf424f37f

2021-12-30

Fix mypy databricks operator (#20598)

d56e7b56bb

2021-12-30

Fix template_fields type to have MyPy friendly Sequence type (#20571)

a0821235fb

2021-12-30

Use typed Context EVERYWHERE (#20565)

c5c18c54fa

2021-12-29

Databricks: fix verification of Managed Identity (#20550)

d3b3161f0d

2021-12-28

Remove 'host' as an instance attr in 'DatabricksHook' (#20540)

58afc19377

2021-12-28

Add 'wait_for_termination' argument for Databricks Operators (#20536)

e7659d08b0

2021-12-27

Update connection object to ''cached_property'' in ''DatabricksHook'' (#20526)

cad39274d9

2021-12-14

Fix MyPy Errors for Databricks provider. (#20265)

+
+
+

2.1.0

+

Latest change: 2021-12-10

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

820bfed515

2021-12-10

Prepare docs for provider's RC2 release (#20205)

66f94f95c2

2021-12-10

Remove db call from 'DatabricksHook.__init__()' (#20180)

545ca59ba9

2021-12-08

Unhide changelog entry for databricks (#20128)

637db1a0ba

2021-12-07

Update documentation for RC2 release of November Databricks Provider (#20086)

728e94a47e

2021-12-05

Refactor DatabricksHook (#19835)

4925b37b66

2021-12-04

Databricks hook: fix expiration time check (#20036)

853576d901

2021-11-30

Update documentation for November 2021 provider's release (#19882)

11998848a4

2021-11-24

Databricks: add more methods to represent run state information (#19723)

56bdfe7a84

2021-11-22

Databricks - allow Azure SP authentication on other Azure clouds (#19722)

244627e3da

2021-11-14

Databricks: allow to specify PAT in Password field (#19585)

0a4a8bdb94

2021-11-14

Databricks jobs 2.1 (#19544)

8ae878953b

2021-11-09

Update Databricks API from 2.0 to 2.1 (#19412)

28b51fb7bd

2021-11-08

Authentication with AAD tokens in Databricks provider (#19335)

3a0c455855

2021-11-07

Update Databricks operators to match latest version of API 2.0 (#19443)

d9567eb106

2021-10-29

Prepare documentation for October Provider's release (#19321)

f5ad26dcdd

2021-10-21

Fixup string concatenations (#19099)

+
+
+

2.0.2

+

Latest change: 2021-09-30

+ +++++ + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

840ea3efb9

2021-09-30

Update documentation for September providers release (#18613)

ef037e7021

2021-09-29

Static start_date and default arg cleanup for misc. provider example DAGs (#18597)

0b7b13372f

2021-09-18

Move DB call out of ''DatabricksHook.__init__'' (#18339)

+
+
+

2.0.1

+

Latest change: 2021-08-30

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

0a68588479

2021-08-30

Add August 2021 Provider's documentation (#17890)

be75dcd39c

2021-08-23

Update description about the new ''connection-types'' provider meta-data

76ed2a49c6

2021-08-19

Import Hooks lazily individually in providers manager (#17682)

87f408b1e7

2021-07-26

Prepares docs for Rc2 release of July providers (#17116)

b916b75079

2021-07-15

Prepare documentation for July release of providers. (#17015)

866a601b76

2021-06-28

Removes pylint from our toolchain (#16682)

+
+
+

2.0.0

+

Latest change: 2021-06-18

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

bbc627a3da

2021-06-18

Prepares documentation for rc2 release of Providers (#16501)

cbf8001d76

2021-06-16

Synchronizes updated changelog after buggfix release (#16464)

1fba5402bb

2021-06-15

More documentation update for June providers release (#16405)

9c94b72d44

2021-06-07

Updated documentation for June 2021 provider release (#16294)

37681bca00

2021-05-07

Auto-apply apply_default decorator (#15667)

807ad32ce5

2021-05-01

Prepares provider release after PIP 21 compatibility (#15576)

df143aee8d

2021-04-29

An initial rework of the "Concepts" docs (#15444)

49cae1f052

2021-04-17

Add documentation for Databricks connection (#15410)

68e4c4dcb0

2021-03-20

Remove Backport Providers (#14886)

+
+
+

1.0.1

+

Latest change: 2021-02-04

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

88bdcfa0df

2021-02-04

Prepare to release a new wave of providers. (#14013)

ac2f72c98d

2021-02-01

Implement provider versioning tools (#13767)

a9ac2b040b

2021-01-23

Switch to f-strings using flynt. (#13732)

3fd5ef3555

2021-01-21

Add missing logos for integrations (#13717)

295d66f914

2020-12-30

Fix Grammar in PIP warning (#13380)

6cf76d7ac0

2020-12-18

Fix typo in pip upgrade command :( (#13148)

+
+
+

1.0.0

+

Latest change: 2020-12-09

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

32971a1a2d

2020-12-09

Updates providers versions to 1.0.0 (#12955)

b40dffa085

2020-12-08

Rename remaing modules to match AIP-21 (#12917)

9b39f24780

2020-12-08

Add support for dynamic connection form fields per provider (#12558)

bd90136aaf

2020-11-30

Move operator guides to provider documentation packages (#12681)

c34ef853c8

2020-11-20

Separate out documentation building per provider  (#12444)

0080354502

2020-11-18

Update provider READMEs for 1.0.0b2 batch release (#12449)

7ca0b6f121

2020-11-18

Enable Markdownlint rule MD003/heading-style/header-style (#12427) (#12438)

ae7cb4a1e2

2020-11-17

Update wrong commit hash in backport provider changes (#12390)

6889a333cf

2020-11-15

Improvements for operators and hooks ref docs (#12366)

7825e8f590

2020-11-13

Docs installation improvements (#12304)

b027223132

2020-11-13

Add install/uninstall api to databricks hook (#12316)

85a18e13d9

2020-11-09

Point at pypi project pages for cross-dependency of provider packages (#12212)

59eb5de78c

2020-11-09

Update provider READMEs for up-coming 1.0.0beta1 releases (#12206)

b2a28d1590

2020-11-09

Moves provider packages scripts to dev (#12082)

7e0d08e1f0

2020-11-09

Add how-to Guide for Databricks operators (#12175)

4e8f9cc8d0

2020-11-03

Enable Black - Python Auto Formmatter (#9550)

8c42cf1b00

2020-11-03

Use PyUpgrade to use Python 3.6 features (#11447)

5a439e84eb

2020-10-26

Prepare providers release 0.0.2a1 (#11855)

872b1566a1

2020-10-25

Generated backport providers readmes/setup for 2020.10.29 (#11826)

349b0811c3

2020-10-20

Add D200 pydocstyle check (#11688)

16e7129719

2020-10-13

Added support for provider packages for Airflow 2.0 (#11487)

0a0e1af800

2020-10-03

Fix Broken Markdown links in Providers README TOC (#11249)

ca4238eb4d

2020-10-02

Fixed month in backport packages to October (#11242)

5220e4c384

2020-10-02

Prepare Backport release 2020.09.07 (#11238)

54353f8745

2020-09-27

Increase type coverage for five different providers (#11170)

966a06d96b

2020-09-18

Fetching databricks host from connection if not supplied in extras. (#10762)

9549274d11

2020-09-09

Upgrade black to 20.8b1 (#10818)

fdd9b6f65b

2020-08-25

Enable Black on Providers Packages (#10543)

bfefcce0c9

2020-08-25

Updated REST API call so GET requests pass payload in query string instead of request body (#10462)

3696c34c28

2020-08-24

Fix typo in the word "release" (#10528)

2f2d8dbfaf

2020-08-25

Remove all "noinspection" comments native to IntelliJ (#10525)

ee7ca128a1

2020-08-22

Fix broken Markdown refernces in Providers README (#10483)

cdec301254

2020-08-07

Add correct signature to all operators and sensors (#10205)

7d24b088cd

2020-07-25

Stop using start_date in default_args in example_dags (2) (#9985)

e13a14c873

2020-06-21

Enable & Fix Whitespace related PyDocStyle Checks (#9458)

d0e7db4024

2020-06-19

Fixed release number for fresh release (#9408)

12af6a0800

2020-06-19

Final cleanup for 2020.6.23rc1 release preparation (#9404)

c7e5bce57f

2020-06-19

Prepare backport release candidate for 2020.6.23rc1 (#9370)

f6bd817a3a

2020-06-16

Introduce 'transfers' packages (#9320)

0b0e4f7a4c

2020-05-26

Preparing for RC3 relase of backports (#9026)

00642a46d0

2020-05-26

Fixed name of 20 remaining wrongly named operators. (#8994)

f1073381ed

2020-05-22

Add support for spark python and submit tasks in Databricks operator(#8846)

375d1ca229

2020-05-19

Release candidate 2 for backport packages 2020.05.20 (#8898)

12c5e5d8ae

2020-05-17

Prepare release candidate for backport packages (#8891)

f3521fb0e3

2020-05-16

Regenerate readme files for backport package release (#8886)

92585ca4cb

2020-05-15

Added automated release notes generation for backport operators (#8807)

649935e8ce

2020-04-27

[AIRFLOW-8472]: 'PATCH' for Databricks hook '_do_api_call' (#8473)

16903ba3a6

2020-04-24

[AIRFLOW-8474]: Adding possibility to get job_id from Databricks run (#8475)

5648dfbc30

2020-03-23

Add missing call to Super class in 'amazon', 'cloudant & 'databricks' providers (#7827)

3320e432a1

2020-02-24

[AIRFLOW-6817] Lazy-load 'airflow.DAG' to keep user-facing API untouched (#7517)

4d03e33c11

2020-02-22

[AIRFLOW-6817] remove imports from 'airflow/__init__.py', replaced implicit imports with explicit imports, added entry to 'UPDATING.MD' - squashed/rebased (#7456)

97a429f9d0

2020-02-02

[AIRFLOW-6714] Remove magic comments about UTF-8 (#7338)

83c037873f

2020-01-30

[AIRFLOW-6674] Move example_dags in accordance with AIP-21 (#7287)

c42a375e79

2020-01-27

[AIRFLOW-6644][AIP-21] Move service classes to providers package (#7265)

+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/connections/databricks.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/connections/databricks.html new file mode 100644 index 00000000000..b791fb34b38 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/connections/databricks.html @@ -0,0 +1,954 @@ + + + + + + + + + + + + Databricks Connection — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

Databricks Connection

+

The Databricks connection type enables the Databricks & Databricks SQL Integration.

+
+

Authenticating to Databricks

+

There are several ways to connect to Databricks using Airflow.

+
    +
  1. Use a Personal Access Token (PAT) +i.e. add a token to the Airflow connection. This is the recommended method.

  2. +
  3. Use Databricks login credentials +i.e. add the username and password used to login to the Databricks account to the Airflow connection. +Note that username/password authentication is discouraged and not supported for +DatabricksSqlOperator.

  4. +
  5. Using Azure Active Directory (AAD) token generated from Azure Service Principal's ID and secret +(only on Azure Databricks). Service principal could be defined as a +user inside workspace, or outside of workspace having Owner or Contributor permissions

  6. +
  7. Using Azure Active Directory (AAD) token obtained for Azure managed identity, +when Airflow runs on the VM with assigned managed identity (system-assigned or user-assigned)

  8. +
+
+
+

Default Connection IDs

+

Hooks and operators related to Databricks use databricks_default by default.

+
+
+

Configuring the Connection

+
+
Host (required)

Specify the Databricks workspace URL

+
+
Login (optional)
    +
  • If authentication with Databricks login credentials is used then specify the username used to login to Databricks.

  • +
  • If authentication with Azure Service Principal is used then specify the ID of the Azure Service Principal

  • +
  • If authentication with PAT is used then either leave this field empty or use 'token' as login (both work, the only difference is that if login is empty then token will be sent in request header as Bearer token, if login is 'token' then it will be sent using Basic Auth which is allowed by Databricks API, this may be useful if you plan to reuse this connection with e.g. HttpOperator)

  • +
  • If authentication with Databricks Service Principal OAuth is used then specify the ID of the Service Principal (Databricks on AWS)

  • +
+
+
Password (optional)
    +
  • If authentication with Databricks login credentials is used then specify the password used to login to Databricks.

  • +
  • If authentication with Azure Service Principal is used then specify the secret of the Azure Service Principal

  • +
  • If authentication with PAT is used, then specify PAT (recommended)

  • +
  • If authentication with Databricks Service Principal OAuth is used then specify the secret of the Service Principal (Databricks on AWS)

  • +
+
+
Extra (optional)

Specify the extra parameter (as json dictionary) that can be used in the Databricks connection.

+

Following parameter could be used if using the PAT authentication method:

+
    +
  • token: Specify PAT to use. Consider to switch to specification of PAT in the Password field as it's more secure.

  • +
+

Following parameters are necessary if using authentication with OAuth token for AWS Databricks Service Principal:

+ +

Following parameters are necessary if using authentication with AAD token:

+
    +
  • azure_tenant_id: ID of the Azure Active Directory tenant

  • +
  • azure_resource_id: optional Resource ID of the Azure Databricks workspace (required if Service Principal isn't +a user inside workspace)

  • +
  • azure_ad_endpoint: optional host name of Azure AD endpoint if you're using special Azure Cloud (GovCloud, China, Germany). The value must contain a protocol. For example: https://login.microsoftonline.de.

  • +
+

Following parameters are necessary if using authentication with AAD token for Azure managed identity:

+
    +
  • use_azure_managed_identity: required boolean flag to specify if managed identity needs to be used instead of +service principal

  • +
  • azure_resource_id: optional Resource ID of the Azure Databricks workspace (required if managed identity isn't +a user inside workspace)

  • +
+

Following parameters could be set when using +DatabricksSqlOperator:

+
    +
  • http_path: optional HTTP path of Databricks SQL endpoint or Databricks cluster. See documentation.

  • +
  • session_configuration: optional map containing Spark session configuration parameters.

  • +
  • named internal arguments to the Connection object from databricks-sql-connector package.

  • +
+
+
+

When specifying the connection using an environment variable you should specify +it using URI syntax.

+

Note that all components of the URI should be URL-encoded.

+

For example:

+
export AIRFLOW_CONN_DATABRICKS_DEFAULT='databricks://@host-url?token=yourtoken'
+
+
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/genindex.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/genindex.html new file mode 100644 index 00000000000..195a23df0bc --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/genindex.html @@ -0,0 +1,1685 @@ + + + + + + + + + + + + Index — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ + +

Index

+ +
+ _ + | A + | B + | C + | D + | E + | F + | G + | H + | I + | J + | L + | M + | N + | O + | P + | R + | S + | T + | U + | V + | W + | X + +
+

_

+ + + +
+ +

A

+ + + +
+ +

B

+ + + +
+ +

C

+ + + +
+ +

D

+ + + +
+ +

E

+ + + +
+ +

F

+ + + +
+ +

G

+ + + +
+ +

H

+ + + +
+ +

I

+ + + +
+ +

J

+ + +
+ +

L

+ + + +
+ +

M

+ + +
+ +

N

+ + + +
+ +

O

+ + + +
+ +

P

+ + +
+ +

R

+ + + +
+ +

S

+ + + +
+ +

T

+ + + +
+ +

U

+ + + +
+ +

V

+ + +
+ +

W

+ + +
+ +

X

+ + + +
+ + + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/index.html new file mode 100644 index 00000000000..9916e2a363c --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/index.html @@ -0,0 +1,966 @@ + + + + + + + + + + + + apache-airflow-providers-databricks — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

apache-airflow-providers-databricks

+
+
+
+
+
+
+
+
+
+
+
+
+
+

apache-airflow-providers-databricks package

+

Databricks

+

Release: 6.3.0

+
+
+

Provider package

+

This package is for the databricks provider. +All classes for this package are included in the airflow.providers.databricks python package.

+
+
+

Installation

+

You can install this package on top of an existing Airflow 2 installation via +pip install apache-airflow-providers-databricks. +For the minimum Airflow version supported, see Requirements below.

+
+
+

Requirements

+

The minimum Apache Airflow version supported by this provider package is 2.6.0.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + +

PIP package

Version required

apache-airflow

>=2.6.0

apache-airflow-providers-common-sql

>=1.10.0

requests

>=2.27.0,<3

databricks-sql-connector

>=2.0.0,!=2.9.0,<3.0.0

aiohttp

>=3.9.2,<4

+
+
+

Cross provider package dependencies

+

Those are dependencies that might be needed in order to use all the features of the package. +You need to install the specified provider packages in order to use them.

+

You can install such cross-provider dependencies when installing from PyPI. For example:

+
pip install apache-airflow-providers-databricks[common.sql]
+
+
+ ++++ + + + + + + + + + + +

Dependent package

Extra

apache-airflow-providers-common-sql

common.sql

+
+
+

Downloading official packages

+

You can download officially released packages and verify their checksums and signatures from the +Official Apache Download site

+ +
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/installing-providers-from-sources.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/installing-providers-from-sources.html new file mode 100644 index 00000000000..10f84c19ea8 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/installing-providers-from-sources.html @@ -0,0 +1,974 @@ + + + + + + + + + + + + Installing from sources — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+
+
+

Installing from sources

+
+

Released packages

+

This page describes downloading and verifying apache-airflow-providers-databricks provider version +6.3.0 using officially released packages. +You can also install the provider package - as most Python packages - via +PyPI . +You can choose different version of the provider by selecting different version from the drop-down at +the top-left of the page.

+

The sdist and whl packages released are the "official" sources of installation that you can use if +you want to verify the origin of the packages and want to verify checksums and signatures of the packages. +The packages are available via the +Official Apache Software Foundations Downloads

+

The downloads are available at:

+ +

If you want to install from the source code, you can download from the sources link above, it will contain +a INSTALL file containing details on how you can build and install the provider.

+
+
+

Release integrity

+

PGP signatures KEYS

+

It is essential that you verify the integrity of the downloaded files using the PGP or SHA signatures. +The PGP signatures can be verified using GPG or PGP. Please download the KEYS as well as the asc +signature files for relevant distribution. It is recommended to get these files from the +main distribution directory and not from the mirrors.

+
gpg -i KEYS
+
+
+

or

+
pgpk -a KEYS
+
+
+

or

+
pgp -ka KEYS
+
+
+

To verify the binaries/sources you can download the relevant asc files for it from main +distribution directory and follow the below guide.

+
gpg --verify apache-airflow-providers-********.asc apache-airflow-*********
+
+
+

or

+
pgpv apache-airflow-providers-********.asc
+
+
+

or

+
pgp apache-airflow-providers-********.asc
+
+
+

Example:

+
$ gpg --verify apache-airflow-providers-databricks-6.3.0.tar.gz.asc apache-airflow-providers-databricks-6.3.0.tar.gz
+  gpg: Signature made Sat 11 Sep 12:49:54 2021 BST
+  gpg:                using RSA key CDE15C6E4D3A8EC4ECF4BA4B6674E08AD7DE406F
+  gpg:                issuer "kaxilnaik@apache.org"
+  gpg: Good signature from "Kaxil Naik <kaxilnaik@apache.org>" [unknown]
+  gpg:                 aka "Kaxil Naik <kaxilnaik@gmail.com>" [unknown]
+  gpg: WARNING: The key's User ID is not certified with a trusted signature!
+  gpg:          There is no indication that the signature belongs to the owner.
+  Primary key fingerprint: CDE1 5C6E 4D3A 8EC4 ECF4  BA4B 6674 E08A D7DE 406F
+
+
+

The "Good signature from ..." is indication that the signatures are correct. +Do not worry about the "not certified with a trusted signature" warning. Most of the certificates used +by release managers are self signed, that's why you get this warning. By importing the server in the +previous step and importing it via ID from KEYS page, you know that this is a valid Key already.

+

For SHA512 sum check, download the relevant sha512 and run the following:

+
shasum -a 512 apache-airflow-providers-********  | diff - apache-airflow-providers-********.sha512
+
+
+

The SHASUM of the file should match the one provided in .sha512 file.

+

Example:

+
shasum -a 512 apache-airflow-providers-databricks-6.3.0.tar.gz  | diff - apache-airflow-providers-databricks-6.3.0.tar.gz.sha512
+
+
+
+
+

Verifying PyPI releases

+

You can verify the Provider .whl packages from PyPI by locally downloading the package and signature +and SHA sum files with the script below:

+
#!/bin/bash
+PACKAGE_VERSION=6.3.0
+PACKAGE_NAME=apache-airflow-providers-databricks
+provider_download_dir=$(mktemp -d)
+pip download --no-deps "${PACKAGE_NAME}==${PACKAGE_VERSION}" --dest "${provider_download_dir}"
+curl "https://downloads.apache.org/airflow/providers/apache_airflow_providers_databricks-6.3.0-py3-none-any.whl.asc" \
+    -L -o "${provider_download_dir}/apache_airflow_providers_databricks-6.3.0-py3-none-any.whl.asc"
+curl "https://downloads.apache.org/airflow/providers/apache_airflow_providers_databricks-6.3.0-py3-none-any.whl.sha512" \
+    -L -o "${provider_download_dir}/apache_airflow_providers_databricks-6.3.0-py3-none-any.whl.sha512"
+echo
+echo "Please verify files downloaded to ${provider_download_dir}"
+ls -la "${provider_download_dir}"
+echo
+
+
+

Once you verify the files following the instructions from previous chapter you can remove the temporary +folder created.

+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/objects.inv b/docs-archive/apache-airflow-providers-databricks/6.3.0/objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..a83a4f537fa7e71003f5d85d851f80d78910f0af GIT binary patch literal 2831 zcmV+q3-I(KAX9K?X>NERX>N99Zgg*Qc_4OWa&u{KZXhxWBOp+6Z)#;@bUGkmaA9L; zWi4T8a%OCAcP(&oZ+2;9WpZ;ZWMOn+VsdF?YjX-CAXa5^b7^mGIv_SKGcGU+BOp|0 zWgv28ZDDC{WMy(7Z)PBLXlZjGW@&6?AZc?TV{dJ6a%FRKWn>_Ab7^j8AbMHNEcaO^)}k@~4j z{j^X0#&dz-J2RA@s(6@uLtSUKoGU`BSc_i)E~%NcvUsJSs1g zXH>63QEt0BJx1sa`s0B)LjBPQ+4Hf3%<*tKvBop08b3#-jKpw2(AZ{wW`ZCIGMbXa zNpVUzh8ti?@66E~jONbFw9&}=Vxqy1!N^3;j8&M!32~Yx{vu-1*y-5;7z+F) zakp*&7;!@=Wep4$Fd;MxQn-9HO(4PX=jAYePk-GJmmjj~3P2f=z^C~DPr*SIvo=s< zyV(Y?@spVcF--#omExqF+JZu3hAWKTAt8aSE1E4fKDZg<&Rflf9)MMruS?u042hfi z5vY30LV#mX7JEDI6pDGfQVOls1mN90LSM}pD)uG;Y({V#Ap0WL*qQO|{*m<=#CHG4 za%SkS2_TrMH8n@p*aSf|na`&4nF!8cwFCjlHm7~dhSHyH(_zX517y~>L75%iMB~Zd zAW*XK?vX16LtZc7B34Q|0MRNH766edB@K)yl@iCNh-R)!C|zdvjs~eh0SQnkkst)8 zIMcrUjJ}(;V@+VhIf5H4ocZS$3(P!~RmzJs=CPN6s%SojHhunkVn4IKJunepWAKq| z4uK0TFeNPmoO2mEqMUO|qI>C&`(Mo$b36k{XU_V= z{;ZE2)BbL;E|)9AnEf%gN02#ZlV@`b3{o%^gizQ%vww6(PF|0TO-(Tgc_c{N$?26D zfBPw9MDBgfcK{Jz{Ip*LT^lvs#soBFB?$+H+wvY+;w%vUcTIc1SEMDs(*&a!Ck&Kn zJp~P$2daT?{B=ZAxO5q1b{(&neMf78z1Evnw?TcwK}MjE5}c5vpNWV%00Vf*(<7l9 zc~I)9SP$^|;%D0$JUhr4Or|D?+1SJy4uDP+1(j`nu}$Y28kuZ8HM3ssUTySO(00|y zL}*!bGC7sqQRi2nVK#llrU|OI$bwhoWt+IIQeKlUh_DBgPuFmNB|MEme%C^5A2g$f zEZ+cj{xd4wFPfZbdgyM}Z);{icL{`R#5?XhPu=2Giy)rf-uW z8uulKyh~_`Oy!@0{Gixh(SlBP3FStd+w-x79dR@1u>3oKreqWIqcmvglfYA0fZl;Q z^Vz@@M9HJTE>}Qt8K|9wBR_nFrBHh=anx%E2uPDEglcn;YXdU6ar8bUOOhmb5fGS` zQ&2tv8&Heh49UzRv+4voZ4{zcUpf}~){whDknq)VTSTF%dwo=A(2oNPbqaFC3wQca z2L(IzaPo5{3>f+lbp{mZm{1Y}uh2)UM(Cq!9T?^S+raq{V{Dxp_Aq;f7wSk`M}|At zHnIX6Z~r@(yyPcrtRZ?fe*p06wr>%Ln%Surpba-?4~qYp=z(eHV|-OWfVsV zDf2N~B2SfH|Mb8eO5fD{meg07=Unv#hWYJ&4`M(MVIQTB98o`BADQRZ5Ijg9IfQ+b zK5|42x{t_5g*DPBMuwe2>J28-AIKWdCa6E1+LQ0*5Pg~0Fa4R*dQPn#>v1|(XAs3( zD@-GeYIOrjo%(bO-0LXP708`m0qmYo0Tf3^d{0#BL)2-$o$oEsdKWbcu%-(JnndYFt2F1d_|3`F z%h}G4GG7U{7e}wMBk8@7+gTFo|xG=NlE z%*+?-%%0CgGC6~H0Z}uX!l9)b15%RsIPm{ZZj8ww0@?1B=TYfUc}DeaEy``zr;ibO zVU%oG#Z!`Be8$fPrXZRk5dKHsu^{!fijj(jnIg7 z1x?UMr&j~&V5)cSc4+E-@*=m>ZFz5RN9u|Zqt%T~?VyjZe(K0yNoBOT5v3*lVdHnC zZ+7`GyE3d4-3M?KKt70Iv^hl}M|9ydLPvV%-e@1^*8UA@6V{Gm$e+$|6;8X;MSSuBROB2X|3B%A3JPyFHZFZzI!XnzxV)$q*JbWJyM&h2LHd@VxuK zBfCRk$nI<@(#j$ls=jVHzBB&vj+6u6klI91fs`UMTDm@KfGxeK9hG%}p~Wqvn%(6o}*^I{DKuZ`!z(6C6;^kRo2jp{pIW7LDv5wx;=xJZVrz3}Q=k9pVYA5XIx}d6B12BAi9Lgv8w|7hxJ8DzVOI%FnM8NV4!EMfpYMOE5Kw zXD%-=YI;~5H$TwPcOMq^!&T)u|F&J1Mp@z#dMNus;-V85$vXUDXZO(9L|%ge#M^H1 zKxBUr&Q_rc4Lz$$bgJW>>q}?WSB}SrIHw zBA=67O>r!`;ec&TwwIr+JSSVEXq0_;Fta9Ge0}+xY>}c-_ThoPs_fl2;G4yYhc$@@ z*J~LEhM`$dVKGh^gC?auA?Q%)&uVf-4=yOkbepcD@K8@E!HK&*%qV^nc^vV4$_7A| h*3A+>-By{4-$ZJgwJoMxfy=ZpPMI;G#y_Kc@HwRCPul + + + + + + + DatabricksCopyIntoOperator — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

DatabricksCopyIntoOperator

+

Use the DatabricksCopyIntoOperator to import +data into Databricks table using COPY INTO +command.

+
+

Using the Operator

+

Operator loads data from a specified location into a table using a configured endpoint. The only required parameters are:

+
    +
  • table_name - string with the table name

  • +
  • file_location - string with the URI of data to load

  • +
  • file_format - string specifying the file format of data to load. Supported formats are CSV, JSON, AVRO, ORC, PARQUET, TEXT, BINARYFILE.

  • +
  • One of sql_endpoint_name (name of Databricks SQL endpoint to use) or http_path (HTTP path for Databricks SQL endpoint or Databricks cluster).

  • +
+

Other parameters are optional and could be found in the class documentation.

+
+
+

Examples

+
+

Importing CSV data

+

An example usage of the DatabricksCopyIntoOperator to import CSV data into a table is as follows:

+
+

tests/system/providers/databricks/example_databricks_sql.py[source]

+
    # Example of importing data using COPY_INTO SQL command
+    import_csv = DatabricksCopyIntoOperator(
+        task_id="import_csv",
+        databricks_conn_id=connection_id,
+        sql_endpoint_name=sql_endpoint_name,
+        table_name="my_table",
+        file_format="CSV",
+        file_location="abfss://container@account.dfs.core.windows.net/my-data/csv",
+        format_options={"header": "true"},
+        force_copy=True,
+    )
+
+
+
+
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/index.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/index.html new file mode 100644 index 00000000000..22d60c3be97 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/index.html @@ -0,0 +1,884 @@ + + + + + + + + + + + + Databricks Operators — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/jobs_create.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/jobs_create.html new file mode 100644 index 00000000000..d67683d9f47 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/jobs_create.html @@ -0,0 +1,997 @@ + + + + + + + + + + + + DatabricksCreateJobsOperator — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

DatabricksCreateJobsOperator

+

Use the DatabricksCreateJobsOperator to create +(or reset) a Databricks job. This operator relies on past XComs to remember the job_id that +was created so that repeated calls with this operator will update the existing job rather than +creating new ones. When paired with the DatabricksRunNowOperator all runs will fall under the same +job within the Databricks UI.

+
+

Using the Operator

+

There are three ways to instantiate this operator. In the first way, you can take the JSON payload that you typically use +to call the api/2.1/jobs/create endpoint and pass it directly to our DatabricksCreateJobsOperator through the +json parameter. With this approach you get full control over the underlying payload to Jobs REST API, including +execution of Databricks jobs with multiple tasks, but it's harder to detect errors because of the lack of the type checking.

+

The second way to accomplish the same thing is to use the named parameters of the DatabricksCreateJobsOperator directly. Note that there is exactly +one named parameter for each top level parameter in the api/2.1/jobs/create endpoint.

+

The third way is to use both the json parameter AND the named parameters. They will be merged +together. If there are conflicts during the merge, the named parameters will take precedence and +override the top level json keys.

+
+
Currently the named parameters that DatabricksCreateJobsOperator supports are:
    +
  • name

  • +
  • tags

  • +
  • tasks

  • +
  • job_clusters

  • +
  • email_notifications

  • +
  • webhook_notifications

  • +
  • timeout_seconds

  • +
  • schedule

  • +
  • max_concurrent_runs

  • +
  • git_source

  • +
  • access_control_list

  • +
+
+
+
+
+

Examples

+
+

Specifying parameters as JSON

+

An example usage of the DatabricksCreateJobsOperator is as follows:

+
+

tests/system/providers/databricks/example_databricks.py[source]

+
    # Example of using the JSON parameter to initialize the operator.
+    job = {
+        "tasks": [
+            {
+                "task_key": "test",
+                "job_cluster_key": "job_cluster",
+                "notebook_task": {
+                    "notebook_path": "/Shared/test",
+                },
+            },
+        ],
+        "job_clusters": [
+            {
+                "job_cluster_key": "job_cluster",
+                "new_cluster": {
+                    "spark_version": "7.3.x-scala2.12",
+                    "node_type_id": "i3.xlarge",
+                    "num_workers": 2,
+                },
+            },
+        ],
+    }
+
+    jobs_create_json = DatabricksCreateJobsOperator(task_id="jobs_create_json", json=job)
+
+
+
+
+
+

Using named parameters

+

You can also use named parameters to initialize the operator and run the job.

+
+

tests/system/providers/databricks/example_databricks.py[source]

+
    # Example of using the named parameters to initialize the operator.
+    tasks = [
+        {
+            "task_key": "test",
+            "job_cluster_key": "job_cluster",
+            "notebook_task": {
+                "notebook_path": "/Shared/test",
+            },
+        },
+    ]
+    job_clusters = [
+        {
+            "job_cluster_key": "job_cluster",
+            "new_cluster": {
+                "spark_version": "7.3.x-scala2.12",
+                "node_type_id": "i3.xlarge",
+                "num_workers": 2,
+            },
+        },
+    ]
+
+    jobs_create_named = DatabricksCreateJobsOperator(
+        task_id="jobs_create_named", tasks=tasks, job_clusters=job_clusters
+    )
+
+
+
+
+
+

Pairing with DatabricksRunNowOperator

+

You can use the job_id that is returned by the DatabricksCreateJobsOperator in the +return_value XCom as an argument to the DatabricksRunNowOperator to run the job.

+
+

tests/system/providers/databricks/example_databricks.py[source]

+
    # Example of using the DatabricksRunNowOperator after creating a job with DatabricksCreateJobsOperator.
+    run_now = DatabricksRunNowOperator(
+        task_id="run_now", job_id="{{ ti.xcom_pull(task_ids='jobs_create_named') }}"
+    )
+
+    jobs_create_named >> run_now
+
+
+
+
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/repos_create.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/repos_create.html new file mode 100644 index 00000000000..27a01425bf8 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/repos_create.html @@ -0,0 +1,940 @@ + + + + + + + + + + + + DatabricksReposCreateOperator — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

DatabricksReposCreateOperator

+

Use the DatabricksReposCreateOperator to create (and optionally checkout) a +Databricks Repos +via api/2.0/repos API endpoint.

+
+

Using the Operator

+

To use this operator you need to provide at least git_url parameter.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Input

git_url: str

Required HTTPS URL of a Git repository

git_provider: str

Optional name of Git provider. Must be provided if we can't guess its name from URL. See API documentation for actual list of supported Git providers.

branch: str

Optional name of the existing Git branch to checkout.

tag: str

Optional name of the existing Git tag to checkout.

repo_path: str

Optional path to a Databricks Repos, like, /Repos/<user_email>/repo_name. If not specified, it will be created in the user's directory.

ignore_existing_repo: bool

Don't throw exception if repository with given path already exists.

databricks_conn_id: string

the name of the Airflow connection to use.

databricks_retry_limit: integer

amount of times retry if the Databricks backend is unreachable.

databricks_retry_delay: decimal

number of seconds to wait between retries.

+
+

Examples

+
+
+
+

Create a Databricks Repo

+

An example usage of the DatabricksReposCreateOperator is as follows:

+
+

tests/system/providers/databricks/example_databricks_repos.py[source]

+
    # Example of creating a Databricks Repo
+    repo_path = "/Repos/user@domain.com/demo-repo"
+    git_url = "https://github.com/test/test"
+    create_repo = DatabricksReposCreateOperator(task_id="create_repo", repo_path=repo_path, git_url=git_url)
+
+
+
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/repos_delete.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/repos_delete.html new file mode 100644 index 00000000000..8b843e417a6 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/repos_delete.html @@ -0,0 +1,927 @@ + + + + + + + + + + + + DatabricksReposDeleteOperator — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

DatabricksReposDeleteOperator

+

Use the DatabricksReposDeleteOperator to delete an existing +Databricks Repo +via api/2.0/repos/ API endpoint.

+
+

Using the Operator

+

To use this operator you need to provide either repo_path or repo_id.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Input

repo_path: str

Path to existing Databricks Repos, like, /Repos/<user_email>/repo_name (required if repo_id isn't provided).

repo_id: str

ID of existing Databricks Repos (required if repo_path isn't provided).

databricks_conn_id: string

the name of the Airflow connection to use.

databricks_retry_limit: integer

amount of times retry if the Databricks backend is unreachable.

databricks_retry_delay: decimal

number of seconds to wait between retries.

+
+

Examples

+
+
+
+

Deleting Databricks Repo by specifying path

+

An example usage of the DatabricksReposDeleteOperator is as follows:

+
+

tests/system/providers/databricks/example_databricks_repos.py[source]

+
    # Example of deleting a Databricks Repo
+    repo_path = "/Repos/user@domain.com/demo-repo"
+    delete_repo = DatabricksReposDeleteOperator(task_id="delete_repo", repo_path=repo_path)
+
+
+
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/repos_update.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/repos_update.html new file mode 100644 index 00000000000..0859757ef8a --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/repos_update.html @@ -0,0 +1,934 @@ + + + + + + + + + + + + DatabricksReposUpdateOperator — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

DatabricksReposUpdateOperator

+

Use the DatabricksReposUpdateOperator to update code in an existing +Databricks Repos to a given Git branch or tag +via api/2.0/repos/ API endpoint.

+
+

Using the Operator

+

Usually this operator is used to update a source code of the Databricks job before its execution. +To use this operator you need to provide either branch or tag and either repo_path or repo_id.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Input

branch: str

Name of the existing Git branch to update to (required if tag isn't provided).

tag: str

Name of the existing Git tag to update to (required if branch isn't provided).

repo_path: str

Path to existing Databricks Repos, like, /Repos/<user_email>/repo_name (required if repo_id isn't provided).

repo_id: str

ID of existing Databricks Repos (required if repo_path isn't provided).

databricks_conn_id: string

the name of the Airflow connection to use.

databricks_retry_limit: integer

amount of times retry if the Databricks backend is unreachable.

databricks_retry_delay: decimal

number of seconds to wait between retries.

+
+

Examples

+
+
+
+

Updating Databricks Repo by specifying path

+

An example usage of the DatabricksReposUpdateOperator is as follows:

+
+

tests/system/providers/databricks/example_databricks_repos.py[source]

+
    # Example of updating a Databricks Repo to the latest code
+    repo_path = "/Repos/user@domain.com/demo-repo"
+    update_repo = DatabricksReposUpdateOperator(task_id="update_repo", repo_path=repo_path, branch="releases")
+
+
+
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/run_now.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/run_now.html new file mode 100644 index 00000000000..cad978523c8 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/run_now.html @@ -0,0 +1,904 @@ + + + + + + + + + + + + DatabricksRunNowOperator — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

DatabricksRunNowOperator

+

Use the DatabricksRunNowOperator to trigger a run of an existing Databricks job +via api/2.1/jobs/run-now API endpoint.

+
+

Using the Operator

+

There are two ways to instantiate this operator. In the first way, you can take the JSON payload that you typically use +to call the api/2.1/jobs/run-now endpoint and pass it directly to our DatabricksRunNowOperator through the json parameter.

+

Another way to accomplish the same thing is to use the named parameters of the DatabricksRunNowOperator directly. +Note that there is exactly one named parameter for each top level parameter in the jobs/run-now endpoint.

+

The only required parameters are either:

+
    +
  • job_id - to specify ID of the existing Databricks job

  • +
  • job_name - Name of the existing Databricks job. It will throw exception if job isn't found, of if there are multiple jobs with the same name.

  • +
+

All other parameters are optional and described in documentation for DatabricksRunNowOperator. For example, you can pass additional parameters to a job using one of the following parameters, depending on the type of tasks in the job:

+
    +
  • notebook_params

  • +
  • python_params

  • +
  • python_named_parameters

  • +
  • jar_params

  • +
  • spark_submit_params

  • +
  • idempotency_token

  • +
  • repair_run

  • +
  • cancel_previous_runs

  • +
+
+
+
+

DatabricksRunNowDeferrableOperator

+

Deferrable version of the DatabricksRunNowOperator operator.

+

It allows to utilize Airflow workers more effectively using new functionality introduced in Airflow 2.2.0

+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/sql.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/sql.html new file mode 100644 index 00000000000..0000e476ed7 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/sql.html @@ -0,0 +1,1074 @@ + + + + + + + + + + + + DatabricksSqlOperator — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

DatabricksSqlOperator

+

Use the DatabricksSqlOperator to execute SQL +on a Databricks SQL warehouse or a +Databricks cluster.

+
+

Using the Operator

+

Operator executes given SQL queries against configured warehouse. The only required parameters are:

+
    +
  • sql - SQL queries to execute. There are 3 ways of specifying SQL queries:

    +
      +
    1. Simple string with SQL statement.

    2. +
    3. List of strings representing SQL statements.

    4. +
    5. Name of the file with SQL queries. File must have .sql extension. Each query should finish with ;<new_line>

    6. +
    +
  • +
  • One of sql_warehouse_name (name of Databricks SQL warehouse to use) or http_path (HTTP path for Databricks SQL warehouse or Databricks cluster).

  • +
+

Other parameters are optional and could be found in the class documentation.

+
+
+

Examples

+
+

Selecting data

+

An example usage of the DatabricksSqlOperator to select data from a table is as follows:

+
+

tests/system/providers/databricks/example_databricks_sql.py[source]

+
    # Example of using the Databricks SQL Operator to select data.
+    select = DatabricksSqlOperator(
+        databricks_conn_id=connection_id,
+        sql_endpoint_name=sql_endpoint_name,
+        task_id="select_data",
+        sql="select * from default.my_airflow_table",
+    )
+
+
+
+
+
+

Selecting data into a file

+

An example usage of the DatabricksSqlOperator to select data from a table and store in a file is as follows:

+
+

tests/system/providers/databricks/example_databricks_sql.py[source]

+
    # Example of using the Databricks SQL Operator to select data into a file with JSONL format.
+    select_into_file = DatabricksSqlOperator(
+        databricks_conn_id=connection_id,
+        sql_endpoint_name=sql_endpoint_name,
+        task_id="select_data_into_file",
+        sql="select * from default.my_airflow_table",
+        output_path="/tmp/1.jsonl",
+        output_format="jsonl",
+    )
+
+
+
+
+
+

Executing multiple statements

+

An example usage of the DatabricksSqlOperator to perform multiple SQL statements is as follows:

+
+

tests/system/providers/databricks/example_databricks_sql.py[source]

+
    # Example of using the Databricks SQL Operator to perform multiple operations.
+    create = DatabricksSqlOperator(
+        databricks_conn_id=connection_id,
+        sql_endpoint_name=sql_endpoint_name,
+        task_id="create_and_populate_table",
+        sql=[
+            "drop table if exists default.my_airflow_table",
+            "create table default.my_airflow_table(id int, v string)",
+            "insert into default.my_airflow_table values (1, 'test 1'), (2, 'test 2')",
+        ],
+    )
+
+
+
+
+
+

Executing multiple statements from a file

+

An example usage of the DatabricksSqlOperator to perform statements from a file is as follows:

+
+

tests/system/providers/databricks/example_databricks_sql.py[source]

+
    # Example of using the Databricks SQL Operator to select data.
+    # SQL statements should be in the file with name test.sql
+    create_file = DatabricksSqlOperator(
+        databricks_conn_id=connection_id,
+        sql_endpoint_name=sql_endpoint_name,
+        task_id="create_and_populate_from_file",
+        sql="test.sql",
+    )
+
+
+
+
+
+
+
+

DatabricksSqlSensor

+

Use the DatabricksSqlSensor to run the sensor +for a table accessible via a Databricks SQL warehouse or interactive cluster.

+
+

Using the Sensor

+

The sensor executes the SQL statement supplied by the user. The only required parameters are:

+
    +
  • sql - SQL query to execute for the sensor.

  • +
  • One of sql_warehouse_name (name of Databricks SQL warehouse to use) or http_path (HTTP path for Databricks SQL warehouse or Databricks cluster).

  • +
+

Other parameters are optional and could be found in the class documentation.

+
+
+

Examples

+

Configuring Databricks connection to be used with the Sensor.

+
+

tests/system/providers/databricks/example_databricks_sensors.py[source]

+
# Connection string setup for Databricks workspace.
+connection_id = "databricks_default"
+sql_warehouse_name = "Starter Warehouse"
+
+
+
+

Poking the specific table with the SQL statement:

+
+

tests/system/providers/databricks/example_databricks_sensors.py[source]

+
# Example of using the Databricks SQL Sensor to check existence of data in a table.
+sql_sensor = DatabricksSqlSensor(
+    databricks_conn_id=connection_id,
+    sql_warehouse_name=sql_warehouse_name,
+    catalog="hive_metastore",
+    task_id="sql_sensor_task",
+    sql="select * from hive_metastore.temp.sample_table_3 limit 1",
+    timeout=60 * 2,
+)
+
+
+
+
+
+
+

DatabricksPartitionSensor

+

Sensors are a special type of Operator that are designed to do exactly one thing - wait for something to occur. It can be time-based, or waiting for a file, or an external event, but all they do is wait until something happens, and then succeed so their downstream tasks can run.

+

For the Databricks Partition Sensor, we check if a partition and its related value exists and if not, it waits until the partition value arrives. The waiting time and interval to check can be configured in the timeout and poke_interval parameters respectively.

+

Use the DatabricksPartitionSensor to run the sensor +for a table accessible via a Databricks SQL warehouse or interactive cluster.

+
+

Using the Sensor

+

The sensor accepts the table name and partition name(s), value(s) from the user and generates the SQL query to check if +the specified partition name, value(s) exist in the specified table.

+

The required parameters are:

+
    +
  • table_name (name of the table for partition check).

  • +
  • partitions (name of the partitions to check).

  • +
  • partition_operator (comparison operator for partitions, to be used for range or limit of values, such as partition_name >= partition_value). Databricks comparison operators are supported.

  • +
  • One of sql_warehouse_name (name of Databricks SQL warehouse to use) or http_path (HTTP path for Databricks SQL warehouse or Databricks cluster).

  • +
+

Other parameters are optional and can be found in the class documentation.

+
+
+

Examples

+

Configuring Databricks connection to be used with the Sensor.

+
+

tests/system/providers/databricks/example_databricks_sensors.py[source]

+
# Connection string setup for Databricks workspace.
+connection_id = "databricks_default"
+sql_warehouse_name = "Starter Warehouse"
+
+
+
+

Poking the specific table for existence of data/partition:

+
+

tests/system/providers/databricks/example_databricks_sensors.py[source]

+
# Example of using the Databricks Partition Sensor to check the presence
+# of the specified partition(s) in a table.
+partition_sensor = DatabricksPartitionSensor(
+    databricks_conn_id=connection_id,
+    sql_warehouse_name=sql_warehouse_name,
+    catalog="hive_metastore",
+    task_id="partition_sensor_task",
+    table_name="sample_table_2",
+    schema="temp",
+    partitions={"date": "2023-01-03", "name": ["abc", "def"]},
+    partition_operator="=",
+    timeout=60 * 2,
+)
+
+
+
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/submit_run.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/submit_run.html new file mode 100644 index 00000000000..37f0ce870bc --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/operators/submit_run.html @@ -0,0 +1,1004 @@ + + + + + + + + + + + + DatabricksSubmitRunOperator — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

DatabricksSubmitRunOperator

+

Use the DatabricksSubmitRunOperator to submit +a new Databricks job via Databricks api/2.1/jobs/runs/submit API endpoint.

+
+

Using the Operator

+

There are three ways to instantiate this operator. In the first way, you can take the JSON payload that you typically use +to call the api/2.1/jobs/runs/submit endpoint and pass it directly to our DatabricksSubmitRunOperator through the +json parameter. With this approach you get full control over the underlying payload to Jobs REST API, including +execution of Databricks jobs with multiple tasks, but it's harder to detect errors because of the lack of the type checking.

+
json = {
+    "new_cluster": {"spark_version": "2.1.0-db3-scala2.11", "num_workers": 2},
+    "notebook_task": {
+        "notebook_path": "/Users/airflow@example.com/PrepareData",
+    },
+}
+notebook_run = DatabricksSubmitRunOperator(task_id="notebook_run", json=json)
+
+
+

The second way to accomplish the same thing is to use the named parameters of the DatabricksSubmitRunOperator directly. Note that there is exactly +one named parameter for each top level parameter in the runs/submit endpoint. When using named parameters you must to specify following:

+
    +
  • Task specification - it should be one of:

    +
      +
    • spark_jar_task - main class and parameters for the JAR task

    • +
    • notebook_task - notebook path and parameters for the task

    • +
    • spark_python_task - python file path and parameters to run the python file with

    • +
    • spark_submit_task - parameters needed to run a spark-submit command

    • +
    • pipeline_task - parameters needed to run a Delta Live Tables pipeline

    • +
    • dbt_task - parameters needed to run a dbt project

    • +
    +
  • +
  • Cluster specification - it should be one of: +* new_cluster - specs for a new cluster on which this task will be run +* existing_cluster_id - ID for existing cluster on which to run this task

  • +
  • pipeline_task - may refer to either a pipeline_id or pipeline_name

  • +
+

In the case where both the json parameter AND the named parameters +are provided, they will be merged together. If there are conflicts during the merge, +the named parameters will take precedence and override the top level json keys.

+
+
Currently the named parameters that DatabricksSubmitRunOperator supports are
    +
  • spark_jar_task

  • +
  • notebook_task

  • +
  • spark_python_task

  • +
  • spark_submit_task

  • +
  • pipeline_task

  • +
  • dbt_task

  • +
  • git_source

  • +
  • new_cluster

  • +
  • existing_cluster_id

  • +
  • libraries

  • +
  • run_name

  • +
  • timeout_seconds

  • +
+
+
+
new_cluster = {"spark_version": "10.1.x-scala2.12", "num_workers": 2}
+notebook_task = {
+    "notebook_path": "/Users/airflow@example.com/PrepareData",
+}
+notebook_run = DatabricksSubmitRunOperator(
+    task_id="notebook_run", new_cluster=new_cluster, notebook_task=notebook_task
+)
+
+
+

Another way to do is use the param tasks to pass array of objects to instantiate this operator. Here the value of tasks param that is used to invoke api/2.1/jobs/runs/submit endpoint is passed through the tasks param in DatabricksSubmitRunOperator. Instead of invoking single task, you can pass array of task and submit a one-time run.

+
tasks = [
+    {
+        "new_cluster": {"spark_version": "2.1.0-db3-scala2.11", "num_workers": 2},
+        "notebook_task": {"notebook_path": "/Users/airflow@example.com/PrepareData"},
+    }
+]
+notebook_run = DatabricksSubmitRunOperator(task_id="notebook_run", tasks=tasks)
+
+
+
+
+

Examples

+
+

Specifying parameters as JSON

+

An example usage of the DatabricksSubmitRunOperator is as follows:

+
+

tests/system/providers/databricks/example_databricks.py[source]

+
    # Example of using the JSON parameter to initialize the operator.
+    new_cluster = {
+        "spark_version": "9.1.x-scala2.12",
+        "node_type_id": "r3.xlarge",
+        "aws_attributes": {"availability": "ON_DEMAND"},
+        "num_workers": 8,
+    }
+
+    notebook_task_params = {
+        "new_cluster": new_cluster,
+        "notebook_task": {
+            "notebook_path": "/Users/airflow@example.com/PrepareData",
+        },
+    }
+
+    notebook_task = DatabricksSubmitRunOperator(task_id="notebook_task", json=notebook_task_params)
+
+
+
+
+
+

Using named parameters

+

You can also use named parameters to initialize the operator and run the job.

+
+

tests/system/providers/databricks/example_databricks.py[source]

+
    # Example of using the named parameters of DatabricksSubmitRunOperator
+    # to initialize the operator.
+    spark_jar_task = DatabricksSubmitRunOperator(
+        task_id="spark_jar_task",
+        new_cluster=new_cluster,
+        spark_jar_task={"main_class_name": "com.example.ProcessData"},
+        libraries=[{"jar": "dbfs:/lib/etl-0.1.jar"}],
+    )
+
+
+
+
+
+
+
+

DatabricksSubmitRunDeferrableOperator

+

Deferrable version of the DatabricksSubmitRunOperator operator.

+

It allows to utilize Airflow workers more effectively using new functionality introduced in Airflow 2.2.0

+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/output-spelling-results-apache-airflow-providers-databricks/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css b/docs-archive/apache-airflow-providers-databricks/6.3.0/output-spelling-results-apache-airflow-providers-databricks/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css new file mode 100644 index 00000000000..eb19f698afc --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/output-spelling-results-apache-airflow-providers-databricks/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css @@ -0,0 +1 @@ +.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative}details.sd-dropdown .sd-summary-title{font-weight:700;padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary{list-style:none;padding:1em}details.sd-dropdown summary .sd-octicon.no-title{vertical-align:middle}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown summary::-webkit-details-marker{display:none}details.sd-dropdown summary:focus{outline:none}details.sd-dropdown .sd-summary-icon{margin-right:.5em}details.sd-dropdown .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary:hover .sd-summary-up svg,details.sd-dropdown summary:hover .sd-summary-down svg{opacity:1;transform:scale(1.1)}details.sd-dropdown .sd-summary-up svg,details.sd-dropdown .sd-summary-down svg{display:block;opacity:.6}details.sd-dropdown .sd-summary-up,details.sd-dropdown .sd-summary-down{pointer-events:none;position:absolute;right:1em;top:1em}details.sd-dropdown[open]>.sd-summary-title .sd-summary-down{visibility:hidden}details.sd-dropdown:not([open])>.sd-summary-title .sd-summary-up{visibility:hidden}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #0071bc;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0060a0;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem} diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/output-spelling-results-apache-airflow-providers-databricks/_sphinx_design_static/design-tabs.js b/docs-archive/apache-airflow-providers-databricks/6.3.0/output-spelling-results-apache-airflow-providers-databricks/_sphinx_design_static/design-tabs.js new file mode 100644 index 00000000000..36b38cf0d91 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/output-spelling-results-apache-airflow-providers-databricks/_sphinx_design_static/design-tabs.js @@ -0,0 +1,27 @@ +var sd_labels_by_text = {}; + +function ready() { + const li = document.getElementsByClassName("sd-tab-label"); + for (const label of li) { + syncId = label.getAttribute("data-sync-id"); + if (syncId) { + label.onclick = onLabelClick; + if (!sd_labels_by_text[syncId]) { + sd_labels_by_text[syncId] = []; + } + sd_labels_by_text[syncId].push(label); + } + } +} + +function onLabelClick() { + // Activate other inputs with the same sync id. + syncId = this.getAttribute("data-sync-id"); + for (label of sd_labels_by_text[syncId]) { + if (label === this) continue; + label.previousElementSibling.checked = true; + } + window.localStorage.setItem("sphinx-design-last-tab", syncId); +} + +document.addEventListener("DOMContentLoaded", ready, false); diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/py-modindex.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/py-modindex.html new file mode 100644 index 00000000000..8bd2178b1c9 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/py-modindex.html @@ -0,0 +1,970 @@ + + + + + + + + + + + + Python Module Index — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/search.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/search.html new file mode 100644 index 00000000000..5f9d74f5dc7 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/search.html @@ -0,0 +1,887 @@ + + + + + + + + + + + + Search — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Search

+ + + + +

+ Searching for multiple words only shows matches that contain + all words. +

+ + +
+ + + +
+ + + +
+ +
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/searchindex.js b/docs-archive/apache-airflow-providers-databricks/6.3.0/searchindex.js new file mode 100644 index 00000000000..a32a21dcfb1 --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"docnames": ["_api/airflow/providers/databricks/hooks/databricks/index", "_api/airflow/providers/databricks/hooks/databricks_base/index", "_api/airflow/providers/databricks/hooks/databricks_sql/index", "_api/airflow/providers/databricks/hooks/index", "_api/airflow/providers/databricks/index", "_api/airflow/providers/databricks/operators/databricks/index", "_api/airflow/providers/databricks/operators/databricks_repos/index", "_api/airflow/providers/databricks/operators/databricks_sql/index", "_api/airflow/providers/databricks/operators/index", "_api/airflow/providers/databricks/sensors/databricks_partition/index", "_api/airflow/providers/databricks/sensors/databricks_sql/index", "_api/airflow/providers/databricks/sensors/index", "_api/airflow/providers/databricks/triggers/databricks/index", "_api/airflow/providers/databricks/triggers/index", "_api/airflow/providers/databricks/utils/databricks/index", "_api/airflow/providers/databricks/utils/index", "_api/tests/system/providers/databricks/example_databricks/index", "_api/tests/system/providers/databricks/example_databricks_repos/index", "_api/tests/system/providers/databricks/example_databricks_sensors/index", "_api/tests/system/providers/databricks/example_databricks_sql/index", "_api/tests/system/providers/databricks/index", "changelog", "commits", "connections/databricks", "index", "installing-providers-from-sources", "operators/copy_into", "operators/index", "operators/jobs_create", "operators/repos_create", "operators/repos_delete", "operators/repos_update", "operators/run_now", "operators/sql", "operators/submit_run", "security"], "filenames": ["_api/airflow/providers/databricks/hooks/databricks/index.rst", "_api/airflow/providers/databricks/hooks/databricks_base/index.rst", "_api/airflow/providers/databricks/hooks/databricks_sql/index.rst", "_api/airflow/providers/databricks/hooks/index.rst", "_api/airflow/providers/databricks/index.rst", "_api/airflow/providers/databricks/operators/databricks/index.rst", "_api/airflow/providers/databricks/operators/databricks_repos/index.rst", "_api/airflow/providers/databricks/operators/databricks_sql/index.rst", "_api/airflow/providers/databricks/operators/index.rst", "_api/airflow/providers/databricks/sensors/databricks_partition/index.rst", "_api/airflow/providers/databricks/sensors/databricks_sql/index.rst", "_api/airflow/providers/databricks/sensors/index.rst", "_api/airflow/providers/databricks/triggers/databricks/index.rst", "_api/airflow/providers/databricks/triggers/index.rst", "_api/airflow/providers/databricks/utils/databricks/index.rst", "_api/airflow/providers/databricks/utils/index.rst", "_api/tests/system/providers/databricks/example_databricks/index.rst", "_api/tests/system/providers/databricks/example_databricks_repos/index.rst", "_api/tests/system/providers/databricks/example_databricks_sensors/index.rst", "_api/tests/system/providers/databricks/example_databricks_sql/index.rst", "_api/tests/system/providers/databricks/index.rst", "changelog.rst", "commits.rst", "connections/databricks.rst", "index.rst", "installing-providers-from-sources.rst", "operators/copy_into.rst", "operators/index.rst", "operators/jobs_create.rst", "operators/repos_create.rst", "operators/repos_delete.rst", "operators/repos_update.rst", "operators/run_now.rst", "operators/sql.rst", "operators/submit_run.rst", "security.rst"], "titles": ["airflow.providers.databricks.hooks.databricks", "airflow.providers.databricks.hooks.databricks_base", "airflow.providers.databricks.hooks.databricks_sql", "airflow.providers.databricks.hooks", "airflow.providers.databricks", "airflow.providers.databricks.operators.databricks", "airflow.providers.databricks.operators.databricks_repos", "airflow.providers.databricks.operators.databricks_sql", "airflow.providers.databricks.operators", "airflow.providers.databricks.sensors.databricks_partition", "airflow.providers.databricks.sensors.databricks_sql", "airflow.providers.databricks.sensors", "airflow.providers.databricks.triggers.databricks", "airflow.providers.databricks.triggers", "airflow.providers.databricks.utils.databricks", "airflow.providers.databricks.utils", "tests.system.providers.databricks.example_databricks", "tests.system.providers.databricks.example_databricks_repos", "tests.system.providers.databricks.example_databricks_sensors", "tests.system.providers.databricks.example_databricks_sql", "tests.system.providers.databricks", "Changelog", "Package apache-airflow-providers-databricks", "Databricks Connection", "apache-airflow-providers-databricks", "Installing from sources", "DatabricksCopyIntoOperator", "Databricks Operators", "DatabricksCreateJobsOperator", "DatabricksReposCreateOperator", "DatabricksReposDeleteOperator", "DatabricksReposUpdateOperator", "DatabricksRunNowOperator", "DatabricksSqlOperator", "DatabricksSubmitRunOperator", "Releasing security patches"], "terms": {"thi": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35], "enabl": [0, 1, 22, 23], "submit": [0, 1, 5, 22, 34], "run": [0, 1, 2, 5, 9, 10, 12, 16, 19, 21, 22, 23, 25, 28, 32, 33, 34], "job": [0, 1, 5, 16, 21, 22, 28, 31, 32, 34], "platform": [0, 1], "intern": [0, 1, 2, 7, 9, 10, 23], "oper": [0, 1, 4, 9, 21, 22, 23], "talk": [0, 1], "api": [0, 1, 2, 5, 6, 12, 16, 21, 22, 23, 28, 29, 30, 31, 32, 34], "2": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35], "1": [0, 1, 5, 6, 24, 28, 32, 33, 34], "now": [0, 5, 7, 21, 22, 32], "endpoint": [0, 1, 2, 5, 6, 7, 21, 22, 23, 26, 28, 29, 30, 31, 32, 34], "http": [0, 1, 2, 5, 6, 7, 9, 10, 16, 21, 22, 23, 25, 26, 29, 33], "doc": [0, 5, 6, 16, 21, 22], "com": [0, 1, 5, 6, 16, 17, 21, 25, 29, 30, 31, 34], "dev": [0, 5, 6, 22], "tool": [0, 5, 6, 22], "latest": [0, 5, 6, 16, 21, 22, 31, 35], "html": [0, 5, 6, 16], "jobsrunnow": [0, 5], "_": 0, "get_cluster_endpoint": 0, "get": [0, 2, 5, 7, 10, 21, 22, 25, 28, 34, 35], "0": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35], "cluster": [0, 2, 5, 7, 9, 10, 16, 23, 26, 33, 34], "sourc": [0, 1, 2, 4, 5, 6, 7, 9, 10, 12, 14, 16, 17, 18, 19, 26, 28, 29, 30, 31, 33, 34], "restart_cluster_endpoint": 0, "post": [0, 6], "restart": 0, "start_cluster_endpoint": 0, "start": 0, "terminate_cluster_endpoint": 0, "delet": [0, 6, 21, 22], "create_endpoint": 0, "creat": [0, 5, 6, 7, 10, 16, 19, 21, 22, 25, 28, 33], "reset_endpoint": 0, "reset": [0, 5, 21, 22, 28], "run_now_endpoint": 0, "submit_run_endpoint": 0, "get_run_endpoint": 0, "cancel_run_endpoint": 0, "cancel": [0, 5, 21, 22], "delete_run_endpoint": 0, "repair_run_endpoint": 0, "repair": [0, 5, 21, 22], "output_runs_job_endpoint": 0, "output": [0, 7, 19, 21, 22], "cancel_all_runs_endpoint": 0, "all": [0, 2, 5, 7, 9, 10, 14, 21, 22, 23, 24, 28, 32, 33, 35], "install_libs_endpoint": 0, "librari": [0, 1, 5, 34], "instal": [0, 21, 22, 35], "uninstall_libs_endpoint": 0, "uninstal": [0, 22], "list_jobs_endpoint": 0, "list": [0, 2, 5, 7, 9, 10, 21, 22, 29, 33], "list_pipelines_endpoint": 0, "pipelin": [0, 5, 21, 22, 34], "workspace_get_status_endpoint": 0, "workspac": [0, 5, 16, 23, 33], "statu": [0, 21, 22], "spark_versions_endpoint": 0, "spark": [0, 2, 5, 7, 9, 10, 16, 22, 23, 34], "version": [0, 2, 5, 7, 9, 10, 21, 22, 24, 25, 32, 34, 35], "runstat": [0, 16], "life_cycle_st": 0, "result_st": [0, 16], "state_messag": 0, "arg": [0, 5, 22], "kwarg": [0, 2, 5, 6, 7, 9, 10], "util": [0, 4, 6, 32, 34], "state": [0, 16, 21, 22], "concept": [0, 22], "properti": 0, "is_termin": 0, "bool": [0, 2, 5, 6, 7, 29], "true": [0, 2, 5, 7, 14, 23, 26], "current": [0, 2, 5, 28, 34], "i": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35], "termin": [0, 5], "is_success": 0, "result": [0, 2, 5, 9, 10, 12, 21, 22], "success": [0, 16], "run_life_cycle_st": [0, 21, 22], "pend": 0, "skip": [0, 21, 22], "internal_error": 0, "queu": [0, 21, 22], "__eq__": 0, "other": [0, 5, 21, 22, 26, 32, 33], "return": [0, 1, 2, 5, 6, 7, 9, 10, 12, 21, 22, 28], "self": [0, 5, 14, 25], "valu": [0, 5, 6, 7, 14, 19, 21, 22, 23, 33, 34], "__repr__": 0, "repr": 0, "to_json": 0, "classmethod": 0, "from_json": 0, "data": [0, 7, 19, 21, 22], "clusterst": [0, 21, 22], "is_run": 0, "cluster_life_cycle_st": 0, "resiz": 0, "error": [0, 21, 22, 28, 34], "unknown": [0, 1, 25], "databrickshook": [0, 21, 22], "databricks_conn_id": [0, 1, 2, 5, 6, 7, 9, 10, 12, 21, 22, 26, 29, 30, 31, 33], "basedatabrickshook": [0, 1, 2], "default_conn_nam": [0, 1, 2, 7, 9, 10], "timeout_second": [0, 1, 5, 28, 34], "180": [0, 1], "retry_limit": [0, 1, 12], "3": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35], "retry_delai": [0, 1, 12], "retry_arg": [0, 1, 12], "none": [0, 1, 2, 5, 6, 7, 9, 10, 12, 25], "caller": [0, 1, 2], "base": [0, 1, 2, 5, 6, 7, 9, 10, 12, 21, 22, 33], "databricks_bas": [0, 2, 3, 4], "interact": [0, 1, 2, 33], "paramet": [0, 1, 2, 5, 6, 7, 9, 10, 12, 21, 22, 23, 26, 29, 30, 31, 32, 33], "str": [0, 1, 2, 5, 6, 7, 9, 10, 12, 22, 29, 30, 31], "refer": [0, 1, 2, 5, 6, 7, 9, 10, 12, 16, 34], "connect": [0, 1, 2, 5, 6, 7, 9, 10, 12, 21, 22, 29, 30, 31, 33], "int": [0, 1, 5, 6, 7, 12, 33], "The": [0, 1, 2, 5, 12, 14, 16, 19, 21, 23, 24, 25, 26, 28, 32, 33, 34, 35], "amount": [0, 1, 5, 6, 29, 30, 31], "time": [0, 1, 5, 6, 12, 21, 22, 29, 30, 31, 33, 34], "second": [0, 1, 5, 6, 12, 16, 19, 28, 29, 30, 31, 34], "request": [0, 1, 2, 5, 7, 9, 10, 22, 23, 24], "wait": [0, 1, 5, 6, 12, 29, 30, 31, 33], "befor": [0, 1, 2, 5, 21, 22, 31], "out": [0, 1, 6, 21, 22, 35], "number": [0, 1, 5, 6, 7, 12, 22, 29, 30, 31], "retri": [0, 1, 5, 6, 12, 21, 22, 29, 30, 31], "case": [0, 1, 5, 6, 12, 21, 34, 35], "servic": [0, 1, 12, 21, 22, 23], "outag": [0, 1, 12], "float": [0, 1, 5, 6], "between": [0, 1, 5, 6, 12, 29, 30, 31], "might": [0, 1, 5, 6, 24, 35], "point": [0, 1, 5, 6, 22], "dict": [0, 1, 2, 5, 7, 9, 10, 12, 14, 21, 22], "ani": [0, 1, 2, 5, 7, 9, 10, 12, 21, 25], "an": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35], "option": [0, 1, 2, 5, 6, 7, 9, 10, 12, 21, 22, 23, 26, 29, 32, 33], "dictionari": [0, 1, 2, 5, 6, 7, 9, 10, 12, 23], "argument": [0, 1, 5, 12, 21, 22, 23, 28], "pass": [0, 1, 2, 5, 7, 12, 19, 22, 28, 32, 34], "tenac": [0, 1, 5, 12], "hook_nam": [0, 2], "create_job": 0, "json": [0, 5, 7, 14, 21, 22, 23, 26, 32], "call": [0, 2, 5, 12, 21, 22, 28, 32, 34], "us": [0, 2, 5, 6, 7, 9, 10, 12, 16, 19, 21, 22, 23, 24, 25, 35], "bodi": [0, 22], "job_id": [0, 5, 21, 22, 28, 32], "type": [0, 5, 7, 12, 14, 21, 22, 23, 28, 32, 33, 34], "reset_job": 0, "new_set": 0, "run_now": [0, 28], "run_id": [0, 5, 12], "submit_run": 0, "list_job": [0, 21, 22], "limit": [0, 33], "25": [0, 22], "expand_task": 0, "fals": [0, 2, 5, 6, 12, 14], "job_nam": [0, 5, 32], "page_token": [0, 21], "batch": [0, 22], "size": 0, "retriev": [0, 5, 21, 22], "whether": [0, 2, 5], "includ": [0, 22, 24, 28, 34, 35], "task": [0, 5, 12, 16, 19, 21, 22, 28, 32, 33, 34], "detail": [0, 5, 21, 22, 25], "respons": [0, 21, 22], "name": [0, 2, 5, 6, 7, 9, 10, 21, 22, 23, 26, 29, 30, 31, 32, 33], "search": [0, 21, 22], "page": [0, 12, 22, 25], "token": [0, 1, 5, 6, 21, 22, 23], "first": [0, 5, 7, 16, 19, 21, 22, 28, 32, 34], "A": [0, 5], "find_job_id_by_nam": 0, "find": 0, "id": [0, 5, 6, 7, 9, 10, 12, 21, 22, 25, 30, 31, 32, 33, 34], "its": [0, 6, 21, 29, 31, 33], "ar": [0, 5, 7, 12, 21, 22, 23, 24, 25, 26, 28, 32, 33, 34, 35], "multipl": [0, 28, 32, 34], "same": [0, 5, 6, 7, 21, 28, 32, 34], "rais": 0, "airflowexcept": 0, "look": [0, 5, 7], "up": [0, 5, 22], "wa": [0, 2, 5, 12, 21, 28], "found": [0, 26, 32, 33, 35], "list_pipelin": 0, "batch_siz": 0, "pipeline_nam": [0, 34], "notebook_path": [0, 28, 34], "delta": [0, 5, 19, 34], "live": [0, 5, 34], "tabl": [0, 2, 5, 7, 9, 19, 26, 33, 34], "cannot": [0, 5, 21, 22], "combin": 0, "path": [0, 2, 5, 6, 7, 9, 10, 12, 16, 19, 21, 22, 23, 26, 29, 33, 34], "notebook": [0, 5, 16, 34], "find_pipeline_id_by_nam": 0, "pipeline_id": [0, 5, 34], "guid": [0, 5, 7, 22, 25], "string": [0, 2, 7, 9, 10, 14, 21, 22, 26, 29, 30, 31, 33], "get_run_page_url": 0, "run_page_url": [0, 5, 12], "url": [0, 6, 12, 23, 29], "async": [0, 1, 12, 21, 22], "a_get_run_page_url": 0, "get_job_id": 0, "from": [0, 5, 6, 7, 10, 14, 19, 21, 22, 23, 24, 26, 29, 35], "given": [0, 5, 6, 7, 29, 31, 33], "get_run_st": 0, "pleas": [0, 21, 25], "note": [0, 2, 5, 22, 23, 28, 32, 34], "method": [0, 5, 21, 22, 23], "failur": [0, 5], "unless": [0, 2], "you": [0, 5, 21, 23, 24, 25, 28, 29, 30, 31, 32, 34, 35], "have": [0, 5, 14, 16, 21, 22, 23, 33, 35], "xcom": [0, 5, 21, 28], "pickl": 0, "can": [0, 5, 6, 7, 14, 21, 23, 24, 25, 28, 29, 32, 33, 34, 35], "done": [0, 35], "follow": [0, 5, 21, 22, 23, 25, 26, 28, 29, 30, 31, 32, 33, 34, 35], "environ": [0, 23], "variabl": [0, 23], "airflow__core__enable_xcom_pickl": 0, "If": [0, 2, 5, 6, 7, 9, 10, 12, 21, 23, 25, 28, 29, 34], "do": [0, 21, 22, 25, 33, 34], "want": [0, 12, 21, 25, 35], "get_run_state_str": 0, "describ": [0, 2, 7, 9, 10, 25, 32], "get_run_state_lifecycl": 0, "get_run_state_result": 0, "get_run_state_messag": 0, "individu": [0, 7, 22], "compon": [0, 23], "a_get_run_st": 0, "get_run": 0, "inform": [0, 5, 7, 12, 16, 21, 22, 35], "a_get_run": 0, "represent": [0, 5], "lifecycl": 0, "messag": 0, "get_run_output": 0, "cancel_run": 0, "cancel_all_run": 0, "activ": [0, 23], "asynchron": [0, 12], "canon": 0, "identifi": 0, "delete_run": 0, "non": [0, 14, 22], "repair_run": [0, 5, 12, 21, 22, 32], "re": [0, 12, 22, 23], "one": [0, 5, 14, 21, 22, 25, 28, 32, 33, 34], "more": [0, 5, 6, 7, 16, 21, 22, 23, 32, 34], "get_latest_repair_id": 0, "exist": [0, 5, 6, 24, 28, 29, 30, 31, 32, 33, 34], "els": [0, 21, 22], "get_cluster_st": 0, "cluster_id": 0, "a_get_cluster_st": 0, "restart_clust": 0, "contain": [0, 5, 6, 7, 9, 10, 14, 23, 25, 26], "specif": [0, 5, 7, 22, 23, 33, 34], "start_clust": 0, "terminate_clust": 0, "function": [0, 2, 5, 10, 21, 22, 32, 34], "arrai": [0, 5, 34], "update_repo": [0, 31], "repo_id": [0, 6, 30, 31], "updat": [0, 6, 21, 22, 28], "repo": [0, 6, 17, 21, 22], "payload": [0, 5, 22, 28, 32, 34], "metadata": [0, 1], "delete_repo": [0, 30], "create_repo": [0, 29], "get_repo_by_path": 0, "obtain": [0, 23], "repositori": [0, 5, 6, 29], "doesn": 0, "t": [0, 2, 6, 7, 21, 22, 23, 29, 30, 31, 32], "update_job_permiss": 0, "permiss": [0, 5, 21, 22, 23], "test_connect": [0, 21, 22], "test": [0, 21, 22, 26, 28, 29, 30, 31, 33, 34, 35], "ui": [0, 5, 28], "6": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35], "10": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35], "dev0": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35], "experiment": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35], "featur": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35], "azure_default_ad_endpoint": 1, "login": [1, 23], "microsoftonlin": [1, 23], "azure_token_service_url": 1, "oauth2": 1, "azure_metadata_service_token_url": 1, "169": 1, "254": 1, "ident": [1, 21, 22, 23], "azure_metadata_service_instance_url": 1, "instanc": [1, 5, 21, 22], "token_refresh_lead_tim": 1, "120": 1, "azure_management_endpoint": 1, "manag": [1, 21, 22, 23, 25], "core": [1, 22, 26], "window": [1, 26], "net": [1, 26], "default_databricks_scop": 1, "2ff814a6": 1, "3304": 1, "4ab8": 1, "85cb": 1, "cd0e6f879c1d": 1, "oidc_token_service_url": 1, "oidc": 1, "v1": 1, "basehook": 1, "conn_name_attr": 1, "databricks_default": [1, 5, 6, 18, 23, 33], "conn_typ": 1, "extra_paramet": 1, "host": [1, 5, 6, 21, 22, 23], "use_azure_managed_ident": [1, 23], "azure_ad_endpoint": [1, 23], "azure_resource_id": [1, 23], "databricks_conn": 1, "get_conn": [1, 2], "user_agent_head": 1, "user_agent_valu": 1, "__aenter__": 1, "__aexit__": 1, "err": 1, "bearerauth": 1, "aiohttp": [1, 21, 22, 24], "basicauth": [1, 21, 22], "onli": [1, 2, 5, 7, 14, 21, 23, 26, 32, 33, 35], "ship": 1, "bearer": [1, 23], "auth": [1, 23], "we": [1, 5, 6, 14, 16, 21, 22, 29, 33, 35], "need": [1, 5, 12, 21, 22, 23, 24, 29, 30, 31, 34], "subclass": 1, "encod": [1, 23], "credenti": [1, 7, 23], "list_sql_endpoints_endpoint": 2, "sql": [2, 7, 9, 10, 19, 21, 22, 23, 24, 26, 33], "databrickssqlhook": [2, 7, 9, 10, 21, 22], "http_path": [2, 7, 9, 10, 23, 26, 33], "sql_endpoint_nam": [2, 7, 26, 33], "session_configur": [2, 7, 9, 10, 23], "http_header": [2, 7, 9, 10], "catalog": [2, 7, 9, 10, 33], "schema": [2, 7, 9, 10, 33], "return_tupl": [2, 21, 22], "common": [2, 5, 6, 7, 21, 22, 24], "dbapihook": [2, 9, 10, 21, 22], "specifi": [2, 5, 6, 7, 9, 10, 19, 21, 22, 23, 24, 26, 29, 32, 33], "should": [2, 5, 6, 7, 9, 10, 12, 21, 22, 23, 25, 33, 34, 35], "either": [2, 5, 7, 9, 10, 12, 23, 30, 31, 32, 34], "": [2, 5, 6, 7, 9, 10, 21, 22, 23, 25, 28, 29, 33, 34], "extra": [2, 5, 6, 7, 9, 10, 21, 22, 23, 24], "must": [2, 5, 6, 7, 9, 10, 14, 23, 29, 33, 34], "abov": [2, 7, 25], "session": [2, 7, 9, 10, 21, 22, 23], "default": [2, 5, 6, 7, 9, 10, 12, 22, 33, 35], "could": [2, 7, 9, 10, 23, 26, 33], "tupl": [2, 7, 9, 10, 12, 21, 22], "k": [2, 7, 9, 10], "v": [2, 7, 9, 10, 33], "pair": [2, 7, 9, 10], "set": [2, 5, 7, 9, 10, 16, 23], "header": [2, 7, 9, 10, 22, 23, 26], "everi": [2, 5, 7, 9, 10, 12], "initi": [2, 7, 9, 10, 21, 22, 28, 34], "requir": [2, 5, 6, 7, 9, 10, 21, 23, 26, 29, 30, 31, 32, 33, 35], "dbr": [2, 7], "9": [2, 7, 9, 10, 21, 22, 24, 34], "namedtupl": [2, 21, 22], "object": [2, 5, 7, 10, 21, 22, 23, 34], "instead": [2, 5, 21, 22, 23, 34], "row": [2, 7, 21, 22], "In": [2, 5, 12, 16, 28, 32, 34], "futur": 2, "releas": [2, 21, 22, 24, 31], "becom": 2, "ensur": [2, 21, 22], "backward": 2, "compat": [2, 21, 22], "dure": [2, 5, 21, 22, 28, 34], "transit": 2, "phase": 2, "flag": [2, 23], "also": [2, 5, 7, 21, 25, 28, 34], "remov": [2, 21, 22, 25], "addit": [2, 7, 9, 10, 32], "connector": [2, 7, 9, 10, 21, 22, 23, 24], "iter": [2, 10], "autocommit": 2, "map": [2, 5, 23], "handler": [2, 9, 10], "split_stat": 2, "return_last": 2, "callabl": [2, 9, 10], "command": [2, 5, 7, 22, 26, 34], "statement": [2, 7, 10, 19, 21, 22], "them": [2, 21, 22, 24], "execut": [2, 5, 6, 7, 10, 16, 21, 22, 28, 31, 34], "sequenti": [2, 16], "what": 2, "queri": [2, 7, 10, 21, 22, 33], "commit": [2, 22], "so": [2, 21, 22, 28, 33, 35], "ha": [2, 16, 21], "effect": [2, 32, 34], "render": [2, 5, 6, 7], "which": [2, 5, 7, 16, 19, 21, 22, 23, 34, 35], "each": [2, 5, 28, 32, 33, 34], "split": 2, "singl": [2, 7, 12, 34], "separ": [2, 22, 35], "last": 2, "after": [2, 21, 22, 28], "express": [2, 7], "abstract": 2, "bulk_dump": 2, "tmp_file": 2, "dump": 2, "databas": [2, 7], "tab": 2, "delimit": 2, "file": [2, 5, 7, 19, 21, 22, 25, 26, 34], "target": 2, "bulk_load": 2, "load": [2, 19, 22, 26], "databricks_sql": [3, 4, 8, 11, 21, 22], "hook": [4, 7, 10, 21, 22, 23], "databricks_repo": [4, 8], "sensor": [4, 21, 22], "databricks_partit": [4, 11], "trigger": [4, 5, 21, 22, 32], "__version__": [4, 22], "defer_method_nam": 5, "execute_complet": [5, 21, 22], "xcom_run_id_kei": 5, "xcom_job_id_kei": 5, "xcom_run_page_url_kei": 5, "databricksjobrunlink": [5, 21, 22], "model": [5, 6, 7, 35], "baseoperatorlink": 5, "construct": [5, 7], "link": [5, 21, 22, 25], "monitor": 5, "see": [5, 6, 14, 21, 22, 23, 24, 29], "get_link": 5, "ti_kei": 5, "extern": [5, 33], "system": [5, 23, 26, 28, 29, 30, 31, 33, 34], "old": [5, 22], "signatur": [5, 22, 24, 25], "dttm": 5, "datetim": 5, "That": [5, 21], "still": [5, 21], "support": [5, 7, 21, 22, 23, 24, 26, 28, 29, 33, 34], "runtim": [5, 9, 10, 21, 22], "deprec": [5, 21, 22], "baseoper": [5, 6, 7], "associ": 5, "taskinstancekei": [5, 22], "taskinst": [5, 21, 22], "databrickscreatejobsoper": [5, 27], "tag": [5, 6, 28, 29, 31], "job_clust": [5, 28], "email_notif": [5, 28], "webhook_notif": [5, 28], "schedul": [5, 28], "max_concurrent_run": [5, 28], "git_sourc": [5, 21, 22, 28, 34], "access_control_list": [5, 28], "polling_period_second": [5, 12], "30": [5, 12, 22], "databricks_retry_limit": [5, 6, 29, 30, 31], "databricks_retry_delai": [5, 6, 29, 30, 31], "databricks_retry_arg": 5, "directli": [5, 28, 32, 34], "e": [5, 12, 23], "etc": 5, "merg": [5, 28, 34], "thei": [5, 12, 14, 28, 33, 34], "conflict": [5, 28, 34], "take": [5, 7, 28, 32, 34], "preced": [5, 28, 34], "overrid": [5, 21, 22, 28, 34], "top": [5, 24, 25, 28, 32, 34], "level": [5, 22, 28, 32, 34], "kei": [5, 6, 25, 28, 34], "templat": [5, 6, 7, 9, 10, 21, 22], "For": [5, 7, 16, 22, 23, 24, 25, 32, 33], "about": [5, 16, 22, 25, 35], "jinja": [5, 6, 7], "jobtaskset": 5, "share": [5, 28], "reus": [5, 23], "jobclust": 5, "jobemailnotif": 5, "webhooknotif": 5, "timeout": [5, 33], "appli": [5, 21, 22], "cronschedul": 5, "maximum": 5, "allow": [5, 21, 22, 23, 32, 34], "concurr": 5, "remot": 5, "gitsourc": 5, "accesscontrolrequestforus": 5, "accesscontrolrequestforgroup": 5, "accesscontrolrequestforserviceprincip": 5, "order": [5, 22, 24], "acl": [5, 21, 22], "consid": [5, 23], "control": [5, 7, 12, 28, 34], "rate": [5, 12], "poll": [5, 12], "By": [5, 6, 12, 25], "backend": [5, 6, 22, 29, 30, 31], "unreach": [5, 6, 29, 30, 31], "Its": [5, 6], "greater": [5, 6], "than": [5, 6, 28], "equal": [5, 6], "template_field": [5, 6, 7, 9, 10, 21, 22], "sequenc": [5, 6, 7, 9, 10, 21, 22], "ui_color": 5, "1cb1c2": 5, "ui_fgcolor": 5, "fff": 5, "context": [5, 6, 7, 9, 10, 12, 22], "deriv": [5, 6, 7, 21, 22], "when": [5, 6, 7, 12, 14, 21, 22, 23, 24, 28, 34, 35], "get_template_context": [5, 6, 7], "databrickssubmitrunoper": [5, 16, 21, 22, 27], "spark_jar_task": [5, 34], "notebook_task": [5, 28, 34], "spark_python_task": [5, 34], "spark_submit_task": [5, 34], "pipeline_task": [5, 21, 22, 34], "dbt_task": [5, 34], "new_clust": [5, 28, 34], "existing_cluster_id": [5, 34], "run_nam": [5, 34], "do_xcom_push": [5, 21, 22], "idempotency_token": [5, 32], "wait_for_termin": [5, 21, 22], "deferr": [5, 21, 22, 32, 34], "conf": 5, "getboolean": 5, "default_deferr": [5, 21, 22], "fallback": 5, "jobsrunssubmit": 5, "There": [5, 21, 23, 25, 28, 32, 33, 34], "three": [5, 28, 34], "wai": [5, 23, 28, 32, 33, 34], "instanti": [5, 12, 28, 32, 34], "how": [5, 7, 22, 25], "runsubmittaskset": 5, "100": 5, "item": 5, "main": [5, 22, 25, 34, 35], "jar": [5, 16, 34], "actual": [5, 29], "OR": 5, "field": [5, 6, 14, 21, 22, 23], "jobssparkjartask": 5, "jobsnotebooktask": 5, "python": [5, 21, 22, 24, 25, 34], "jobssparkpythontask": 5, "jobssparksubmittask": 5, "least": [5, 21, 29], "jobspipelinetask": 5, "dbt": [5, 21, 22, 34], "spec": [5, 34], "new": [5, 16, 21, 22, 28, 32, 34, 35], "except": [5, 6, 14, 21, 22, 29, 32, 35], "jobsclusterspecnewclust": 5, "managedlibrarieslibrari": 5, "task_id": [5, 26, 28, 29, 30, 31, 33, 34], "superclass": 5, "guarante": 5, "idempot": 5, "alreadi": [5, 6, 25, 29], "doe": [5, 14, 21], "most": [5, 25], "64": 5, "charact": [5, 22], "repres": [5, 21, 22, 33], "access": [5, 23, 33], "consist": [5, 21], "subject": [5, 22], "user_nam": 5, "user": [5, 6, 17, 21, 22, 23, 25, 29, 30, 31, 33, 34], "group_nam": 5, "group": 5, "permission_level": 5, "document": [5, 7, 21, 22, 23, 26, 29, 32, 33], "mean": 5, "To": [5, 6, 25, 29, 30, 31], "authent": [5, 6, 7, 21, 22], "leav": [5, 6, 23], "empti": [5, 6, 21, 22, 23], "push": [5, 21], "git": [5, 6, 29, 31], "mode": [5, 21, 22], "template_ext": [5, 7, 9, 10, 21, 22], "tpl": 5, "operator_extra_link": 5, "on_kil": 5, "clean": [5, 22], "subprocess": 5, "kill": 5, "thread": 5, "multiprocess": 5, "within": [5, 21, 22, 28], "ghost": 5, "process": [5, 12, 21, 22], "behind": 5, "event": [5, 12, 14, 21, 22, 33], "databrickssubmitrundeferrableoper": [5, 27], "databricksrunnowoper": [5, 21, 22, 27], "notebook_param": [5, 32], "python_param": [5, 32], "jar_param": [5, 32], "spark_submit_param": [5, 32], "python_named_param": 5, "cancel_previous_run": [5, 21, 22, 32], "two": [5, 16, 32], "typic": [5, 28, 32, 34], "our": [5, 22, 28, 32, 34], "through": [5, 28, 32, 34], "exampl": [5, 9, 16, 19, 22, 23, 24, 25, 32], "42": 5, "dry": 5, "oldest": 5, "1457570074236": 5, "notebook_run": [5, 34], "anoth": [5, 12, 32, 34], "accomplish": [5, 28, 32, 34], "thing": [5, 28, 32, 33, 34], "exactli": [5, 28, 32, 33, 34], "your": [5, 21], "code": [5, 7, 21, 22, 25, 31], "would": 5, "like": [5, 12, 29, 30, 31], "dougla": 5, "adam": 5, "org": [5, 25], "apach": [5, 21, 25], "sparkpi": 5, "where": [5, 34, 35], "both": [5, 16, 23, 28, 34], "AND": [5, 28, 34], "togeth": [5, 7, 28, 34], "python_named_paramet": [5, 32], "It": [5, 25, 32, 33, 34], "mutual": 5, "exclus": 5, "g": [5, 12, 23], "john": 5, "ag": 5, "35": 5, "dbutil": 5, "widget": 5, "upon": 5, "conjunct": 5, "exce": 5, "000": 5, "byte": 5, "line": [5, 22], "overwrit": 5, "wheel": [5, 24], "script": [5, 22, 25], "databricksrunnowdeferrableoper": [5, 21, 22, 27], "databricksreposcreateoper": [6, 27], "git_url": [6, 29], "git_provid": [6, 29], "branch": [6, 29, 31, 35], "repo_path": [6, 17, 29, 30, 31], "ignore_existing_repo": [6, 29], "check": [6, 9, 21, 22, 25, 28, 33, 34], "guess": [6, 29], "format": [6, 7, 19, 21, 22, 26, 33], "folder": [6, 22, 25], "directori": [6, 23, 25, 29], "checkout": [6, 29], "don": [6, 21, 22, 29], "throw": [6, 14, 29, 32], "__git_providers__": 6, "__aws_code_commit_regexp__": 6, "__repos_path_regexp__": 6, "static": [6, 22], "__detect_repo_provider__": 6, "databricksreposupdateoper": [6, 27], "patch": [6, 22], "omit": 6, "databricksreposdeleteoper": [6, 27], "databrickssqloper": [7, 19, 21, 22, 23, 27], "output_path": [7, 33], "output_format": [7, 33], "csv": 7, "csv_param": 7, "client_paramet": [7, 9, 10], "sqlexecutequeryoper": [7, 21, 22], "recogn": 7, "end": [7, 22], "write": 7, "select": [7, 19, 25], "possibl": [7, 22], "jsonl": [7, 33], "dictwrit": 7, "template_fields_render": [7, 9, 10], "conn_id_field": 7, "get_db_hook": 7, "copy_into_approved_format": 7, "avro": [7, 26], "orc": [7, 26], "parquet": [7, 26], "text": [7, 26], "binaryfil": [7, 26], "databrickscopyintooper": [7, 19, 21, 22, 27], "table_nam": [7, 9, 26, 33], "file_loc": [7, 19, 26], "file_format": [7, 26], "pattern": 7, "expression_list": 7, "storage_credenti": 7, "encrypt": 7, "format_opt": [7, 26], "force_copi": [7, 26], "copy_opt": 7, "valid": [7, 14, 21, 22, 25], "copi": [7, 26], "INTO": [7, 26], "piec": 7, "locat": [7, 26], "import": [7, 21, 22, 25], "regex": 7, "match": [7, 21, 22, 25], "configur": [7, 26, 33], "against": [7, 33], "uniti": 7, "storag": 7, "destin": 7, "forc": 7, "integ": [7, 29, 30, 31], "n": 7, "right": 7, "databrickspartitionsensor": [9, 21, 22, 27], "sql_warehouse_nam": [9, 10, 33], "partit": [9, 33], "partition_oper": [9, 33], "fetch_all_handl": [9, 10], "basesensoroper": [9, 10], "detect": [9, 21, 22, 28, 34], "presenc": [9, 33], "warehous": [9, 10, 33], "below": [9, 10, 24, 25], "purpos": [9, 10], "date": [9, 33], "2023": [9, 22, 33], "01": [9, 22, 33], "03": [9, 22, 33], "abc": [9, 33], "def": [9, 33], "comparison": [9, 33], "poke": [9, 10, 33], "databrickssqlsensor": [10, 21, 22, 27], "databricksexecutiontrigg": [12, 14], "basetrigg": 12, "handl": [12, 21, 22], "logic": 12, "commun": 12, "serial": [12, 21, 22], "reconstruct": 12, "keyword": 12, "yield": [12, 21, 22], "whenev": 12, "fire": 12, "off": 12, "finish": [12, 33], "thu": 12, "immedi": 12, "resum": 12, "veri": 12, "quickli": 12, "mai": [12, 22, 23, 34], "workload": 12, "being": 12, "move": [12, 21, 22], "multi": [12, 21, 22], "defer": 12, "assum": 12, "persist": 12, "reli": [12, 21, 28], "cleanup": [12, 22], "longer": 12, "normalise_json_cont": 14, "json_path": 14, "normal": [14, 22], "numer": 14, "boolean": [14, 21, 22, 23], "reason": [14, 21, 35], "why": [14, 25], "becaus": [14, 16, 28, 34], "render_templ": 14, "fail": [14, 21, 22], "convert": [14, 21, 22], "understand": 14, "validate_trigger_ev": 14, "correct": [14, 21, 22, 25], "receiv": [14, 35], "dag": [16, 19, 21, 22], "upload": 16, "dbf": [16, 34], "downstream": [16, 33], "depend": [16, 21, 22, 32, 35], "NOT": 16, "until": [16, 33], "complet": [16, 21], "successfulli": 16, "definit": 16, "env_id": [16, 17, 18, 19], "dag_id": [16, 17, 18, 19], "example_databricks_oper": 16, "test_run": [16, 17, 18, 19], "default_arg": [17, 22], "example_databricks_repos_oper": 17, "domain": [17, 29, 30, 31], "demo": [17, 29, 30, 31], "connection_id": [18, 19, 26, 33], "insert": [19, 33], "third": [19, 28], "store": [19, 33], "fourth": 19, "written": 19, "final": [19, 21, 22], "example_databricks_sql_oper": 19, "my_connect": 19, "example_databrick": [20, 28, 34], "example_databricks_repo": [20, 29, 30, 31], "example_databricks_sensor": [20, 33], "example_databricks_sql": [20, 26, 33], "airflow": [21, 23, 25, 29, 30, 31, 32, 34, 35], "provid": [21, 25, 26, 28, 29, 30, 31, 33, 34, 35], "databrick": [21, 25, 26, 28, 32, 33, 34], "add": [21, 22, 23], "38702": [21, 22], "38619": [21, 22], "param": [21, 22, 34], "38962": [21, 22], "remain": [21, 22], "d401": [21, 22], "37434": [21, 22], "38741": [21, 22], "slash": [21, 22], "38918": [21, 22], "typo": [21, 22], "latest_repair_id": 21, "39050": [21, 22], "refactor": [21, 22], "redund": [21, 22], "block": [21, 22], "38397": [21, 22], "renam": [21, 22], "compli": [21, 22], "38052": [21, 22], "work": [21, 22, 23], "37025": [21, 22], "bump": [21, 22], "min": [21, 22], "avoid": [21, 22], "cve": [21, 22], "2024": [21, 22], "23829": [21, 22], "23334": [21, 22], "37110": [21, 22], "feat": [21, 22], "switch": [21, 22, 23], "class": [21, 22, 24, 26, 33, 34], "decor": [21, 22], "36876": [21, 22], "rid": [21, 22], "pytest": [21, 22], "httpx": [21, 22], "37334": [21, 22], "36601": [21, 22], "36827": [21, 22], "column": [21, 22], "attribut": [21, 22], "36949": [21, 22], "36862": [21, 22], "avail": [21, 25, 34], "explain": 21, "polici": [21, 35], "structur": [21, 22], "dbapi": [21, 22], "36205": 21, "implement": [21, 22], "fetchon": [21, 22], "odbchook": [21, 22], "36161": [21, 22], "minimum": [21, 22, 24], "36017": [21, 22], "36248": [21, 22], "snippet": [21, 22], "docstr": [21, 22], "via": [21, 22, 24, 25, 29, 30, 31, 32, 33, 34], "ruff": [21, 22], "36262": [21, 22], "been": 21, "broken": [21, 22], "make": [21, 22], "pyodbc": [21, 22], "serializ": [21, 22], "make_serializ": [21, 22], "32319": [21, 22], "offset": [21, 22], "favor": 21, "faster": 21, "pagin": [21, 22], "similarli": 21, "34926": [21, 22], "35156": [21, 22], "34643": [21, 22], "respect": [21, 22, 33], "soft_fail": [21, 22], "34544": [21, 22], "34517": [21, 22], "decod": [21, 22], "f": [21, 22], "34518": [21, 22], "34728": [21, 22], "httpbasicauth": [21, 22], "34590": [21, 22], "33472": [21, 22], "deploy": [21, 22], "33886": [21, 22], "accept": [21, 22, 33], "32903": [21, 22], "replac": [21, 22], "concaten": [21, 22], "unpack": [21, 22], "33933": [21, 22], "improv": [21, 22], "modul": [21, 22], "some": [21, 22], "33754": [21, 22], "liter": [21, 22], "33761": [21, 22], "33752": [21, 22], "exclud": [21, 22], "due": [21, 22], "properli": 21, "declar": 21, "urllib3": 21, "github": [21, 22, 29], "issu": 21, "190": 21, "princip": [21, 22, 23], "oauth": [21, 22, 23], "33005": [21, 22], "py": [21, 22, 26, 28, 29, 30, 31, 33, 34], "32340": [21, 22], "33519": [21, 22], "duplic": [21, 22], "sort": [21, 22], "33675": [21, 22], "simplifi": [21, 22], "condit": [21, 22], "len": [21, 22], "33569": [21, 22], "smaller": [21, 22], "33234": [21, 22], "conn": [21, 22], "30784": [21, 22], "32806": [21, 22], "miss": [21, 22], "32689": [21, 22], "accur": [21, 22], "31846": [21, 22], "modifi": [21, 22], "parent": [21, 22], "32253": [21, 22], "config": [21, 22], "31712": [21, 22], "drop": [21, 22, 25, 33], "loop": [21, 22], "stop": [21, 22], "31985": [21, 22], "annot": [21, 22], "31888": [21, 22], "31780": [21, 22], "relat": [21, 22, 23, 33], "again": [21, 22], "31898": [21, 22], "31899": [21, 22], "31703": [21, 22], "30963": [21, 22], "31136": [21, 22], "31038": [21, 22], "databr": [21, 22], "30744": [21, 22], "30786": [21, 22], "30980": [21, 22], "30917": [21, 22], "30761": [21, 22], "inact": [21, 22], "30646": [21, 22], "30477": [21, 22], "taskflow": [21, 22], "29840": [21, 22], "conform": 21, "semant": 21, "kind": 21, "previous": 21, "pre": [21, 22], "cursor": 21, "descript": [21, 22], "just": 21, "last_descript": 21, "suitabl": 21, "gener": [21, 22, 23, 33], "lineag": 21, "analysi": 21, "had": 21, "custom": 21, "behaviour": [21, 22], "adapt": 21, "standard": [21, 22], "approach": [21, 28, 34], "howev": 21, "unchang": 21, "continu": 21, "without": 21, "introduc": [21, 22, 32, 34], "27854": [21, 22], "27888": [21, 22], "27868": [21, 22], "27912": [21, 22], "databricskssqloper": 21, "27196": [21, 22], "urlpars": [21, 22], "urlsplit": [21, 22], "27389": [21, 22], "25717": [21, 22], "27446": [21, 22], "25623": [21, 22], "lower": [21, 22], "bound": [21, 22], "25789": [21, 22], "26628": [21, 22], "agent": [21, 22], "25873": [21, 22], "25578": [21, 22], "25260": [21, 22], "telemetri": [21, 22], "25115": [21, 22], "unifi": [21, 22], "23971": [21, 22], "25114": [21, 22], "deep_string_coerc": [21, 22], "25394": [21, 22], "correctli": [21, 22], "25427": [21, 22], "x": [21, 22, 28, 34], "25674": [21, 22], "ad": [21, 22, 23], "24945": [21, 22], "24617": [21, 22], "24836": [21, 22], "functool": [21, 22], "cached_properti": [21, 22], "24582": [21, 22], "19736": [21, 22], "23620": [21, 22], "defin": [21, 22, 23], "23622": [21, 22], "23641": [21, 22], "unboundlocalerror": [21, 22], "23815": [21, 22], "dbsql": [21, 22], "further": [21, 22], "23199": [21, 22], "22422": [21, 22], "22541": [21, 22], "22886": [21, 22], "22885": [21, 22], "hoc": [21, 22], "22571": [21, 22], "22278": [21, 22], "mistakenli": 21, "install_requir": 21, "22382": 21, "22076": [21, 22], "429": [21, 22], "well": [21, 22, 25], "21852": [21, 22], "22221": [21, 22], "show": [21, 22], "21709": [21, 22], "21663": [21, 22], "18925": [21, 22], "21530": [21, 22], "21363": [21, 22], "januari": [21, 22], "2022": [21, 22], "delai": [21, 22], "21439": [21, 22], "21494": [21, 22], "20536": [21, 22], "20526": [21, 22], "attr": [21, 22], "20540": [21, 22], "verif": [21, 22], "20550": [21, 22], "19723": [21, 22], "azur": [21, 22, 23], "sp": [21, 22], "cloud": [21, 22, 23], "19722": [21, 22], "pat": [21, 22, 23], "password": [21, 22, 23], "19585": [21, 22], "19544": [21, 22], "19412": [21, 22], "aad": [21, 22, 23], "19335": [21, 22], "19443": [21, 22], "db": [21, 22], "__init__": [21, 22], "20180": [21, 22], "fixup": [21, 22], "19099": [21, 22], "expir": [21, 22], "20036": [21, 22], "18339": [21, 22], "optimis": 21, "auto": [21, 22], "apply_default": [21, 22], "15667": [21, 22], "upgrad": [21, 22, 35], "otherwis": 21, "packag": [21, 23], "automat": [21, 22], "manual": 21, "migrat": [21, 22], "readm": [21, 22], "chang": [22, 35], "high": 22, "changelog": 22, "04": 22, "16": 22, "66df296a6e": 22, "fix": [22, 35], "629545bea2": 22, "14": 22, "f9dcc82fb6": 22, "13": 22, "prepar": [22, 35], "1st": 22, "wave": 22, "rc2": 22, "april": 22, "38995": 22, "4a669fb1a9": 22, "11": [22, 25, 34], "5fa80b6aea": 22, "rc1": 22, "38863": 22, "6f21f7dc9b": 22, "4e6d3fa4cf": 22, "08": 22, "39b684d91a": 22, "c74947a69d": 22, "22": 22, "b5b972a106": 22, "18": 22, "yank": 22, "38262": 22, "0a74928894": 22, "38240": 22, "aa75fbb2b8": 22, "restor": 22, "12": [22, 25, 28, 34], "38207": 22, "4742fc0ea5": 22, "15": 22, "8fc984873a": 22, "38070": 22, "83316b8158": 22, "march": 22, "37876": 22, "14d9bff3ad": 22, "02": 22, "24": 22, "37665": 22, "5a0be392e6": 22, "comment": 22, "37488": 22, "e346253760": 22, "bfb054e9e8": 22, "februari": 22, "37326": 22, "78294c24e2": 22, "0c4210af62": 22, "31": 22, "6d748c923b": 22, "dec2662190": 22, "26": 22, "cead3da4a6": 22, "2nd": 22, "round": 22, "jan": 22, "37019": 22, "0b680c9492": 22, "revert": 22, "logger_nam": 22, "logger": 22, "36675": 22, "37015": 22, "c0f7601391": 22, "23": 22, "347373986c": 22, "2b4da0101f": 22, "36945": 22, "13b0930bf4": 22, "17": 22, "574102fd29": 22, "c439ab87c4": 22, "build": [22, 25], "hatchl": 22, "36537": 22, "6bd450da1e": 22, "f7b663d9af": 22, "07": 22, "mypi": 22, "full": [22, 28, 34], "ci": 22, "36638": 22, "19ebcac239": 22, "36640": 22, "6937ae7647": 22, "speed": 22, "autocomplet": 22, "breez": 22, "36499": 22, "77b563bfc5": 22, "break": [22, 35], "36382": 22, "b15d5578da": 22, "decemb": 22, "36380": 22, "f5883d6e7b": 22, "36373": 22, "5fe5d31a46": 22, "322aa649": 22, "21": 22, "e9ba37bb58": 22, "64931b1a65": 22, "36190": 22, "36010f6d0e": 22, "999b70178a": 22, "36112": 22, "d0918d77ee": 22, "0b23d5601c": 22, "novemb": 22, "35836": 22, "99534e47f3": 22, "19": 22, "reproduc": 22, "35693": 22, "064fc2b775": 22, "99df205f42": 22, "reappli": 22, "35686": 22, "1b059c57d6": 22, "35537": 22, "10bac853d2": 22, "28": 22, "d1c58d86de": 22, "3rd": 22, "octob": 22, "35233": 22, "3592ff4046": 22, "35187": 22, "a8784e3c35": 22, "dd7ba3cae1": 22, "292": 22, "35053": 22, "7a93b19138": 22, "daskexecutor": 22, "inclus": 22, "34935": 22, "e9987d5059": 22, "34916": 22, "946b539f0d": 22, "0c8e30e43b": 22, "05": 22, "7ebf4220c9": 22, "09": 22, "usag": [22, 26, 28, 29, 30, 31, 33, 34], "34320": 22, "a1ef232230": 22, "f26fa6d602": 22, "3813ed69c7": 22, "966c2bce9f": 22, "dfec053371": 22, "21990ed894": 22, "34201": 22, "c45617c4d5": 22, "55976af32": 22, "concatin": 22, "f7a005db8c": 22, "9d8c77e447": 22, "27": [22, 24], "b11525702c": 22, "c90eec9365": 22, "c077d19060": 22, "aug": 22, "33730": 22, "dc47c460dc": 22, "4154cc04ce": 22, "2dbb963324": 22, "1cdd82391e": 22, "a91ee7ac2f": 22, "20": 22, "8bf53dd554": 22, "5f8f25b34c": 22, "ecldud": 22, "bug": [22, 35], "33311": 22, "b5a4d36383": 22, "33291": 22, "9736143468": 22, "29": 22, "d06b7af69a": 22, "juli": 22, "32875": 22, "58e21c66fd": 22, "6313e52932": 22, "60c49ab2df": 22, "06": 22, "225e3041d2": 22, "32381": 22, "3878fe6fab": 22, "spuriou": 22, "32373": 22, "cb4927a018": 22, "32298": 22, "f8593503cb": 22, "6b4350e89c": 22, "d1aa509bbd": 22, "d205": 22, "32243": 22, "09d4718d3a": 22, "32125": 22, "79bcc2e668": 22, "june": 22, "32001": 22, "8b146152d6": 22, "32015": 22, "69bc90b824": 22, "66299338eb": 22, "7b096483fa": 22, "049c6184b7": 22, "9276310a43": 22, "31681": 22, "86b5ba2802": 22, "dc5bf3fd02": 22, "discover": 22, "yaml": 22, "31576": 22, "a59076eae": 22, "d400": 22, "pydocstyl": 22, "31427": 22, "9fa75aaf7a": 22, "45548b9451": 22, "31416": 22, "abea189022": 22, "31393": 22, "f5aed58d9f": 22, "circular": 22, "caus": 22, "31379": 22, "d9ff55cf6d": 22, "31252": 22, "fdc7a31aeb": 22, "edd7133a13": 22, "3df0be0f6f": 22, "ac46902154": 22, "31033": 22, "0a30706aa7": 22, "airflowproviderdeprecationwarn": 22, "30975": 22, "eef5bc7f16": 22, "autom": 22, "30994": 22, "a7eb32a5b2": 22, "9409446097": 22, "cli": 22, "cmd": 22, "info": 22, "30822": 22, "ecb9a9ea78": 22, "9bebf85e24": 22, "7d02277ae1": 22, "e46ce78b66": 22, "adhoc": 22, "30787": 22, "37cf0506b5": 22, "1e311cf036": 22, "d23a3bbed8": 22, "mechan": 22, "suspend": 22, "30422": 22, "55dbf1ff1f": 22, "30378": 22, "c3867781e0": 22, "29950": 22, "c405ecb63": 22, "25bdbc8e67": 22, "rc3": 22, "27937": 22, "db5375bea7": 22, "2e20e9f7eb": 22, "relas": 22, "27774": 22, "80c327bd3b": 22, "ea306c9462": 22, "a343bba1e3": 22, "12c3c39d1a": 22, "27613": 22, "00af5c007": 22, "eb06c65556": 22, "9ab1a6a3e7": 22, "style": 22, "26872": 22, "78b8ea2f22": 22, "2a34dc9e84": 22, "27205": 22, "ecd4d6654f": 22, "f8db64c35c": 22, "septemb": 22, "26731": 22, "89e44c46ad": 22, "06acf40a43": 22, "pep": 22, "563": 22, "postpon": 22, "evalu": 22, "26289": 22, "5066844513": 22, "period": 22, "batch02": 22, "25268": 22, "25a9c6a905": 22, "9535ec0bba": 22, "ca9229b6f": 22, "7d0525a55b": 22, "rc4": 22, "25720": 22, "4d32f61fd0": 22, "e5ac6c7cfb": 22, "august": 22, "25618": 22, "52f2f5bfa8": 22, "0255a0a5e7": 22, "679a85325a": 22, "82f842ffc5": 22, "24599": 22, "54a8c4fd2a": 22, "7438707747": 22, "df00436569": 22, "2f70daf5ac": 22, "d2459a241b": 22, "25030": 22, "8dfe7bf5ff": 22, "acaa0635c8": 22, "lazi": 22, "log": 22, "interpol": 22, "24910": 22, "46bbfdade0": 22, "96b01a8012": 22, "bad": 22, "codebas": 22, "24841": 22, "0de31bd73a": 22, "insid": [22, 23], "24672": 22, "510a6bab45": 22, "24702": 22, "ed37c3a0e8": 22, "9c59831ee7": 22, "dcdcf3a2b8": 22, "24307": 22, "717a7588bc": 22, "doubl": 22, "24292": 22, "aeabe994b3": 22, "24231": 22, "027b707d21": 22, "explanatori": 22, "contributor": [22, 23], "24229": 22, "ddf9013098": 22, "aip": 22, "47": 22, "design": [22, 33], "22442": 22, "24203": 22, "acf89510cd": 22, "92ddcf4ac6": 22, "flake8": 22, "implicit": 22, "concat": 22, "plugin": 22, "23873": 22, "6150d28323": 22, "cf5a78e91c": 22, "d0a5b3a4f2": 22, "75c60923e0": 22, "23631": 22, "428a439953": 22, "23591": 22, "a58506b2a6": 22, "address": 22, "review": 22, "6a3d6cc32b": 22, "7b3bf4e435": 22, "f02b0b6b40": 22, "8b6b0848a3": 22, "brees": 22, "pull": 22, "verifi": [22, 24], "imag": 22, "23104": 22, "40831144be": 22, "22979": 22, "7be57eb256": 22, "aa8c08db38": 22, "6933022e94": 22, "22884": 22, "56ab82ed7a": 22, "mid": 22, "22819": 22, "1b12c93ed3": 22, "95169d1d07": 22, "352d7f72dd": 22, "c063fc688c": 22, "black": 22, "precommit": 22, "22521": 22, "d7dbfb7e26": 22, "bugfix": [22, 35], "22383": 22, "cc920963a6": 22, "16adc035b1": 22, "classifi": 22, "22226": 22, "12e9e2c695": 22, "af9d85ccd8": 22, "4014194320": 22, "f5b96315fe": 22, "feb": 22, "22056": 22, "62bf1276f6": 22, "27d19e7626": 22, "a1845c68f9": 22, "7cca82495b": 22, "0a2d0d1ecb": 22, "d94fa37830": 22, "6c3a67d4fc": 22, "2021": [22, 25], "21257": 22, "602abe8394": 22, "sphinx": 22, "autoapi": 22, "typehint": 22, "20951": 22, "f77417eb0d": 22, "k8": 22, "pypi": [22, 24, 35], "20614": 22, "97496ba2b4": 22, "20523": 22, "0bf424f37f": 22, "20598": 22, "d56e7b56bb": 22, "friendli": 22, "20571": 22, "a0821235fb": 22, "everywher": 22, "20565": 22, "c5c18c54fa": 22, "d3b3161f0d": 22, "58afc19377": 22, "e7659d08b0": 22, "cad39274d9": 22, "20265": 22, "820bfed515": 22, "20205": 22, "66f94f95c2": 22, "545ca59ba9": 22, "unhid": 22, "entri": 22, "20128": 22, "637db1a0ba": 22, "20086": 22, "728e94a47": 22, "19835": 22, "4925b37b66": 22, "853576d901": 22, "19882": 22, "11998848a4": 22, "56bdfe7a84": 22, "244627e3da": 22, "0a4a8bdb94": 22, "8ae878953b": 22, "28b51fb7bd": 22, "3a0c455855": 22, "d9567eb106": 22, "19321": 22, "f5ad26dcdd": 22, "840ea3efb9": 22, "18613": 22, "ef037e7021": 22, "start_dat": 22, "misc": 22, "18597": 22, "0b7b13372f": 22, "0a68588479": 22, "17890": 22, "be75dcd39c": 22, "meta": 22, "76ed2a49c6": 22, "lazili": 22, "17682": 22, "87f408b1e7": 22, "17116": 22, "b916b75079": 22, "17015": 22, "866a601b76": 22, "pylint": 22, "toolchain": 22, "16682": 22, "bbc627a3da": 22, "16501": 22, "cbf8001d76": 22, "synchron": 22, "buggfix": 22, "16464": 22, "1fba5402bb": 22, "16405": 22, "9c94b72d44": 22, "16294": 22, "37681bca00": 22, "807ad32ce5": 22, "pip": [22, 24, 25], "15576": 22, "df143aee8d": 22, "rework": 22, "15444": 22, "49cae1f052": 22, "15410": 22, "68e4c4dcb0": 22, "backport": 22, "14886": 22, "88bdcfa0df": 22, "14013": 22, "ac2f72c98d": 22, "13767": 22, "a9ac2b040b": 22, "flynt": 22, "13732": 22, "3fd5ef3555": 22, "logo": 22, "integr": [22, 23], "13717": 22, "295d66f914": 22, "2020": 22, "grammar": 22, "warn": [22, 25], "13380": 22, "6cf76d7ac0": 22, "13148": 22, "32971a1a2d": 22, "12955": 22, "b40dffa085": 22, "rema": 22, "12917": 22, "9b39f24780": 22, "dynam": 22, "form": 22, "per": 22, "12558": 22, "bd90136aaf": 22, "12681": 22, "c34ef853c8": 22, "12444": 22, "0080354502": 22, "0b2": 22, "12449": 22, "7ca0b6f121": 22, "markdownlint": 22, "rule": [22, 35], "md003": 22, "head": 22, "12427": 22, "12438": 22, "ae7cb4a1e2": 22, "wrong": 22, "hash": 22, "12390": 22, "6889a333cf": 22, "ref": 22, "12366": 22, "7825e8f590": 22, "12304": 22, "b027223132": 22, "12316": 22, "85a18e13d9": 22, "project": [22, 34], "cross": 22, "12212": 22, "59eb5de78c": 22, "come": 22, "0beta1": 22, "12206": 22, "b2a28d1590": 22, "12082": 22, "7e0d08e1f0": 22, "12175": 22, "4e8f9cc8d0": 22, "formmatt": 22, "9550": 22, "8c42cf1b00": 22, "pyupgrad": 22, "11447": 22, "5a439e84eb": 22, "2a1": 22, "11855": 22, "872b1566a1": 22, "setup": [22, 33], "11826": 22, "349b0811c3": 22, "d200": 22, "11688": 22, "16e7129719": 22, "11487": 22, "0a0e1af800": 22, "markdown": 22, "toc": 22, "11249": 22, "ca4238eb4d": 22, "month": 22, "11242": 22, "5220e4c384": 22, "11238": 22, "54353f8745": 22, "increas": 22, "coverag": 22, "five": 22, "differ": [22, 23, 25], "11170": 22, "966a06d96b": 22, "fetch": 22, "suppli": [22, 33], "10762": 22, "9549274d11": 22, "8b1": 22, "10818": 22, "fdd9b6f65b": 22, "10543": 22, "bfefcce0c9": 22, "rest": [22, 28, 34], "10462": 22, "3696c34c28": 22, "word": 22, "10528": 22, "2f2d8dbfaf": 22, "noinspect": 22, "nativ": 22, "intellij": 22, "10525": 22, "ee7ca128a1": 22, "refernc": 22, "10483": 22, "cdec301254": 22, "10205": 22, "7d24b088cd": 22, "example_dag": 22, "9985": 22, "e13a14c873": 22, "whitespac": 22, "9458": 22, "d0e7db4024": 22, "fresh": 22, "9408": 22, "12af6a0800": 22, "23rc1": 22, "9404": 22, "c7e5bce57f": 22, "candid": 22, "9370": 22, "f6bd817a3a": 22, "transfer": 22, "9320": 22, "0b0e4f7a4c": 22, "9026": 22, "00642a46d0": 22, "wrongli": 22, "8994": 22, "f1073381ed": 22, "8846": 22, "375d1ca229": 22, "8898": 22, "12c5e5d8a": 22, "8891": 22, "f3521fb0e3": 22, "regener": 22, "8886": 22, "92585ca4cb": 22, "8807": 22, "649935e8c": 22, "8472": 22, "_do_api_cal": 22, "8473": 22, "16903ba3a6": 22, "8474": 22, "8475": 22, "5648dfbc30": 22, "super": 22, "amazon": 22, "cloudant": 22, "7827": 22, "3320e432a1": 22, "6817": 22, "keep": 22, "face": 22, "untouch": 22, "7517": 22, "4d03e33c11": 22, "explicit": 22, "md": 22, "squash": 22, "rebas": 22, "7456": 22, "97a429f9d0": 22, "6714": 22, "magic": 22, "utf": 22, "8": [22, 34], "7338": 22, "83c037873f": 22, "6674": [22, 25], "accord": 22, "7287": 22, "c42a375e79": 22, "6644": 22, "7265": 22, "sever": 23, "person": 23, "recommend": [23, 25], "usernam": 23, "account": [23, 26], "discourag": 23, "secret": 23, "outsid": 23, "owner": [23, 25], "vm": 23, "assign": 23, "sent": 23, "basic": 23, "plan": 23, "httpoper": 23, "aw": 23, "secur": 23, "necessari": 23, "service_principal_oauth": 23, "client": 23, "azure_tenant_id": 23, "tenant": 23, "resourc": 23, "isn": [23, 30, 31, 32], "special": [23, 33], "govcloud": 23, "china": 23, "germani": 23, "protocol": 23, "de": 23, "uri": [23, 26], "syntax": 23, "export": 23, "airflow_conn_databricks_default": 23, "yourtoken": 23, "4": 24, "those": [24, 25], "checksum": [24, 25], "site": 24, "sdist": [24, 25], "asc": [24, 25], "sha512": [24, 25], "download": 25, "offici": 25, "choos": 25, "down": 25, "left": 25, "whl": 25, "origin": 25, "softwar": 25, "foundat": 25, "pgp": 25, "essenti": 25, "sha": 25, "gpg": 25, "relev": 25, "distribut": 25, "mirror": 25, "pgpk": 25, "ka": 25, "binari": 25, "pgpv": 25, "tar": 25, "gz": 25, "made": 25, "sat": 25, "sep": 25, "49": 25, "54": 25, "bst": 25, "rsa": 25, "cde15c6e4d3a8ec4ecf4ba4b6674e08ad7de406f": 25, "issuer": 25, "kaxilnaik": 25, "good": [25, 35], "kaxil": 25, "naik": 25, "aka": 25, "gmail": 25, "certifi": 25, "trust": 25, "indic": 25, "belong": 25, "primari": 25, "fingerprint": 25, "cde1": 25, "5c6e": 25, "4d3a": 25, "8ec4": 25, "ecf4": 25, "ba4b": 25, "e08a": 25, "d7de": 25, "406f": 25, "worri": 25, "certif": 25, "sign": 25, "server": 25, "previou": 25, "step": 25, "know": 25, "sum": 25, "shasum": 25, "512": 25, "diff": 25, "local": 25, "bin": 25, "bash": 25, "package_vers": 25, "package_nam": 25, "provider_download_dir": 25, "mktemp": 25, "d": 25, "dep": 25, "dest": 25, "curl": 25, "apache_airflow_providers_databrick": 25, "py3": 25, "l": 25, "o": 25, "echo": 25, "la": 25, "onc": 25, "instruct": [25, 35], "chapter": 25, "temporari": 25, "One": [26, 33], "copy_into": 26, "import_csv": 26, "my_tabl": 26, "abfss": 26, "df": 26, "my": 26, "past": 28, "rememb": 28, "repeat": 28, "rather": 28, "ones": 28, "fall": 28, "under": 28, "With": [28, 34], "over": [28, 34], "underli": [28, 34], "harder": [28, 34], "lack": [28, 34], "task_kei": 28, "job_cluster_kei": 28, "spark_vers": [28, 34], "7": 28, "scala2": [28, 34], "node_type_id": [28, 34], "i3": 28, "xlarg": [28, 34], "num_work": [28, 34], "jobs_create_json": 28, "jobs_create_nam": 28, "return_valu": 28, "ti": 28, "xcom_pul": 28, "input": [29, 30, 31], "user_email": [29, 30, 31], "repo_nam": [29, 30, 31], "decim": [29, 30, 31], "usual": 31, "worker": [32, 34], "simpl": 33, "extens": 33, "new_lin": 33, "select_data": 33, "my_airflow_t": 33, "select_into_fil": 33, "select_data_into_fil": 33, "tmp": 33, "perform": 33, "create_and_populate_t": 33, "create_fil": 33, "create_and_populate_from_fil": 33, "starter": 33, "sql_sensor": 33, "hive_metastor": 33, "sql_sensor_task": 33, "temp": 33, "sample_table_3": 33, "60": 33, "someth": 33, "occur": 33, "happen": 33, "succe": 33, "arriv": 33, "interv": 33, "poke_interv": 33, "rang": 33, "partition_nam": 33, "partition_valu": 33, "partition_sensor": 33, "partition_sensor_task": 33, "sample_table_2": 33, "db3": 34, "preparedata": 34, "here": 34, "invok": 34, "r3": 34, "aws_attribut": 34, "on_demand": 34, "notebook_task_param": 34, "main_class_nam": 34, "processdata": 34, "lib": 34, "etl": 34, "independ": 35, "itself": 35, "vulner": 35, "publish": 35, "develop": 35, "alwai": 35, "next": 35, "strict": 35, "semver": 35, "scope": 35, "major": 35, "minor": 35, "patchlevel": 35, "critic": 35, "band": 35, "stakehold": 35, "decid": 35, "cherri": 35, "pick": 35, "older": 35, "mix": 35, "govern": 35, "interest": 35, "parti": 35}, "objects": {"airflow.providers": [[4, 0, 0, "-", "databricks"]], "airflow.providers.databricks": [[4, 1, 1, "", "__version__"], [3, 0, 0, "-", "hooks"], [8, 0, 0, "-", "operators"], [11, 0, 0, "-", "sensors"], [13, 0, 0, "-", "triggers"], [15, 0, 0, "-", "utils"]], "airflow.providers.databricks.hooks": [[0, 0, 0, "-", "databricks"], [1, 0, 0, "-", "databricks_base"], [2, 0, 0, "-", "databricks_sql"]], "airflow.providers.databricks.hooks.databricks": [[0, 1, 1, "", "CANCEL_ALL_RUNS_ENDPOINT"], [0, 1, 1, "", "CANCEL_RUN_ENDPOINT"], [0, 1, 1, "", "CREATE_ENDPOINT"], [0, 2, 1, "", "ClusterState"], [0, 1, 1, "", "DELETE_RUN_ENDPOINT"], [0, 2, 1, "", "DatabricksHook"], [0, 1, 1, "", "GET_CLUSTER_ENDPOINT"], [0, 1, 1, "", "GET_RUN_ENDPOINT"], [0, 1, 1, "", "INSTALL_LIBS_ENDPOINT"], [0, 1, 1, "", "LIST_JOBS_ENDPOINT"], [0, 1, 1, "", "LIST_PIPELINES_ENDPOINT"], [0, 1, 1, "", "OUTPUT_RUNS_JOB_ENDPOINT"], [0, 1, 1, "", "REPAIR_RUN_ENDPOINT"], [0, 1, 1, "", "RESET_ENDPOINT"], [0, 1, 1, "", "RESTART_CLUSTER_ENDPOINT"], [0, 1, 1, "", "RUN_NOW_ENDPOINT"], [0, 2, 1, "", "RunState"], [0, 1, 1, "", "SPARK_VERSIONS_ENDPOINT"], [0, 1, 1, "", "START_CLUSTER_ENDPOINT"], [0, 1, 1, "", "SUBMIT_RUN_ENDPOINT"], [0, 1, 1, "", "TERMINATE_CLUSTER_ENDPOINT"], [0, 1, 1, "", "UNINSTALL_LIBS_ENDPOINT"], [0, 1, 1, "", "WORKSPACE_GET_STATUS_ENDPOINT"]], "airflow.providers.databricks.hooks.databricks.ClusterState": [[0, 3, 1, "", "CLUSTER_LIFE_CYCLE_STATES"], [0, 4, 1, "", "__eq__"], [0, 4, 1, "", "__repr__"], [0, 4, 1, "", "from_json"], [0, 5, 1, "", "is_running"], [0, 5, 1, "", "is_terminal"], [0, 4, 1, "", "to_json"]], "airflow.providers.databricks.hooks.databricks.DatabricksHook": [[0, 4, 1, "", "a_get_cluster_state"], [0, 4, 1, "", "a_get_run"], [0, 4, 1, "", "a_get_run_page_url"], [0, 4, 1, "", "a_get_run_state"], [0, 4, 1, "", "cancel_all_runs"], [0, 4, 1, "", "cancel_run"], [0, 4, 1, "", "create_job"], [0, 4, 1, "", "create_repo"], [0, 4, 1, "", "delete_repo"], [0, 4, 1, "", "delete_run"], [0, 4, 1, "", "find_job_id_by_name"], [0, 4, 1, "", "find_pipeline_id_by_name"], [0, 4, 1, "", "get_cluster_state"], [0, 4, 1, "", "get_job_id"], [0, 4, 1, "", "get_latest_repair_id"], [0, 4, 1, "", "get_repo_by_path"], [0, 4, 1, "", "get_run"], [0, 4, 1, "", "get_run_output"], [0, 4, 1, "", "get_run_page_url"], [0, 4, 1, "", "get_run_state"], [0, 4, 1, "", "get_run_state_lifecycle"], [0, 4, 1, "", "get_run_state_message"], [0, 4, 1, "", "get_run_state_result"], [0, 4, 1, "", "get_run_state_str"], [0, 3, 1, "", "hook_name"], [0, 4, 1, "", "install"], [0, 4, 1, "", "list_jobs"], [0, 4, 1, "", "list_pipelines"], [0, 4, 1, "", "repair_run"], [0, 4, 1, "", "reset_job"], [0, 4, 1, "", "restart_cluster"], [0, 4, 1, "", "run_now"], [0, 4, 1, "", "start_cluster"], [0, 4, 1, "", "submit_run"], [0, 4, 1, "", "terminate_cluster"], [0, 4, 1, "", "test_connection"], [0, 4, 1, "", "uninstall"], [0, 4, 1, "", "update_job_permission"], [0, 4, 1, "", "update_repo"]], "airflow.providers.databricks.hooks.databricks.RunState": [[0, 3, 1, "", "RUN_LIFE_CYCLE_STATES"], [0, 4, 1, "", "__eq__"], [0, 4, 1, "", "__repr__"], [0, 4, 1, "", "from_json"], [0, 5, 1, "", "is_successful"], [0, 5, 1, "", "is_terminal"], [0, 4, 1, "", "to_json"]], "airflow.providers.databricks.hooks.databricks_base": [[1, 1, 1, "", "AZURE_DEFAULT_AD_ENDPOINT"], [1, 1, 1, "", "AZURE_MANAGEMENT_ENDPOINT"], [1, 1, 1, "", "AZURE_METADATA_SERVICE_INSTANCE_URL"], [1, 1, 1, "", "AZURE_METADATA_SERVICE_TOKEN_URL"], [1, 1, 1, "", "AZURE_TOKEN_SERVICE_URL"], [1, 2, 1, "", "BaseDatabricksHook"], [1, 2, 1, "", "BearerAuth"], [1, 1, 1, "", "DEFAULT_DATABRICKS_SCOPE"], [1, 1, 1, "", "OIDC_TOKEN_SERVICE_URL"], [1, 1, 1, "", "TOKEN_REFRESH_LEAD_TIME"]], "airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook": [[1, 4, 1, "", "__aenter__"], [1, 4, 1, "", "__aexit__"], [1, 3, 1, "", "conn_name_attr"], [1, 3, 1, "", "conn_type"], [1, 4, 1, "", "databricks_conn"], [1, 3, 1, "", "default_conn_name"], [1, 3, 1, "", "extra_parameters"], [1, 4, 1, "", "get_conn"], [1, 4, 1, "", "host"], [1, 4, 1, "", "user_agent_header"], [1, 4, 1, "", "user_agent_value"]], "airflow.providers.databricks.hooks.databricks_base.BearerAuth": [[1, 4, 1, "", "encode"]], "airflow.providers.databricks.hooks.databricks_sql": [[2, 2, 1, "", "DatabricksSqlHook"], [2, 1, 1, "", "LIST_SQL_ENDPOINTS_ENDPOINT"], [2, 1, 1, "", "T"]], "airflow.providers.databricks.hooks.databricks_sql.DatabricksSqlHook": [[2, 4, 1, "", "bulk_dump"], [2, 4, 1, "", "bulk_load"], [2, 4, 1, "", "get_conn"], [2, 3, 1, "", "hook_name"], [2, 4, 1, "", "run"]], "airflow.providers.databricks.operators": [[5, 0, 0, "-", "databricks"], [6, 0, 0, "-", "databricks_repos"], [7, 0, 0, "-", "databricks_sql"]], "airflow.providers.databricks.operators.databricks": [[5, 1, 1, "", "DEFER_METHOD_NAME"], [5, 2, 1, "", "DatabricksCreateJobsOperator"], [5, 2, 1, "", "DatabricksJobRunLink"], [5, 2, 1, "", "DatabricksRunNowDeferrableOperator"], [5, 2, 1, "", "DatabricksRunNowOperator"], [5, 2, 1, "", "DatabricksSubmitRunDeferrableOperator"], [5, 2, 1, "", "DatabricksSubmitRunOperator"], [5, 1, 1, "", "XCOM_JOB_ID_KEY"], [5, 1, 1, "", "XCOM_RUN_ID_KEY"], [5, 1, 1, "", "XCOM_RUN_PAGE_URL_KEY"]], "airflow.providers.databricks.operators.databricks.DatabricksCreateJobsOperator": [[5, 4, 1, "", "execute"], [5, 3, 1, "", "template_fields"], [5, 3, 1, "", "ui_color"], [5, 3, 1, "", "ui_fgcolor"]], "airflow.providers.databricks.operators.databricks.DatabricksJobRunLink": [[5, 4, 1, "", "get_link"], [5, 3, 1, "", "name"]], "airflow.providers.databricks.operators.databricks.DatabricksRunNowOperator": [[5, 4, 1, "", "execute"], [5, 4, 1, "", "execute_complete"], [5, 4, 1, "", "on_kill"], [5, 3, 1, "", "operator_extra_links"], [5, 3, 1, "", "template_ext"], [5, 3, 1, "", "template_fields"], [5, 3, 1, "", "ui_color"], [5, 3, 1, "", "ui_fgcolor"]], "airflow.providers.databricks.operators.databricks.DatabricksSubmitRunDeferrableOperator": [[5, 4, 1, "", "execute"]], "airflow.providers.databricks.operators.databricks.DatabricksSubmitRunOperator": [[5, 4, 1, "", "execute"], [5, 4, 1, "", "execute_complete"], [5, 4, 1, "", "on_kill"], [5, 3, 1, "", "operator_extra_links"], [5, 3, 1, "", "template_ext"], [5, 3, 1, "", "template_fields"], [5, 3, 1, "", "ui_color"], [5, 3, 1, "", "ui_fgcolor"]], "airflow.providers.databricks.operators.databricks_repos": [[6, 2, 1, "", "DatabricksReposCreateOperator"], [6, 2, 1, "", "DatabricksReposDeleteOperator"], [6, 2, 1, "", "DatabricksReposUpdateOperator"]], "airflow.providers.databricks.operators.databricks_repos.DatabricksReposCreateOperator": [[6, 3, 1, "", "__aws_code_commit_regexp__"], [6, 4, 1, "", "__detect_repo_provider__"], [6, 3, 1, "", "__git_providers__"], [6, 3, 1, "", "__repos_path_regexp__"], [6, 4, 1, "", "execute"], [6, 3, 1, "", "template_fields"]], "airflow.providers.databricks.operators.databricks_repos.DatabricksReposDeleteOperator": [[6, 4, 1, "", "execute"], [6, 3, 1, "", "template_fields"]], "airflow.providers.databricks.operators.databricks_repos.DatabricksReposUpdateOperator": [[6, 4, 1, "", "execute"], [6, 3, 1, "", "template_fields"]], "airflow.providers.databricks.operators.databricks_sql": [[7, 1, 1, "", "COPY_INTO_APPROVED_FORMATS"], [7, 2, 1, "", "DatabricksCopyIntoOperator"], [7, 2, 1, "", "DatabricksSqlOperator"]], "airflow.providers.databricks.operators.databricks_sql.DatabricksCopyIntoOperator": [[7, 4, 1, "", "execute"], [7, 3, 1, "", "template_fields"]], "airflow.providers.databricks.operators.databricks_sql.DatabricksSqlOperator": [[7, 3, 1, "", "conn_id_field"], [7, 4, 1, "", "get_db_hook"], [7, 3, 1, "", "template_ext"], [7, 3, 1, "", "template_fields"], [7, 3, 1, "", "template_fields_renderers"]], "airflow.providers.databricks.sensors": [[9, 0, 0, "-", "databricks_partition"], [10, 0, 0, "-", "databricks_sql"]], "airflow.providers.databricks.sensors.databricks_partition": [[9, 2, 1, "", "DatabricksPartitionSensor"]], "airflow.providers.databricks.sensors.databricks_partition.DatabricksPartitionSensor": [[9, 4, 1, "", "poke"], [9, 3, 1, "", "template_ext"], [9, 3, 1, "", "template_fields"], [9, 3, 1, "", "template_fields_renderers"]], "airflow.providers.databricks.sensors.databricks_sql": [[10, 2, 1, "", "DatabricksSqlSensor"]], "airflow.providers.databricks.sensors.databricks_sql.DatabricksSqlSensor": [[10, 4, 1, "", "hook"], [10, 4, 1, "", "poke"], [10, 3, 1, "", "template_ext"], [10, 3, 1, "", "template_fields"], [10, 3, 1, "", "template_fields_renderers"]], "airflow.providers.databricks.triggers": [[12, 0, 0, "-", "databricks"]], "airflow.providers.databricks.triggers.databricks": [[12, 2, 1, "", "DatabricksExecutionTrigger"]], "airflow.providers.databricks.triggers.databricks.DatabricksExecutionTrigger": [[12, 4, 1, "", "run"], [12, 4, 1, "", "serialize"]], "airflow.providers.databricks.utils": [[14, 0, 0, "-", "databricks"]], "airflow.providers.databricks.utils.databricks": [[14, 6, 1, "", "normalise_json_content"], [14, 6, 1, "", "validate_trigger_event"]], "tests.system.providers": [[20, 0, 0, "-", "databricks"]], "tests.system.providers.databricks": [[16, 0, 0, "-", "example_databricks"], [17, 0, 0, "-", "example_databricks_repos"], [18, 0, 0, "-", "example_databricks_sensors"], [19, 0, 0, "-", "example_databricks_sql"]], "tests.system.providers.databricks.example_databricks": [[16, 1, 1, "", "DAG_ID"], [16, 1, 1, "", "ENV_ID"], [16, 1, 1, "", "job"], [16, 1, 1, "", "test_run"]], "tests.system.providers.databricks.example_databricks_repos": [[17, 1, 1, "", "DAG_ID"], [17, 1, 1, "", "ENV_ID"], [17, 1, 1, "", "default_args"], [17, 1, 1, "", "repo_path"], [17, 1, 1, "", "test_run"]], "tests.system.providers.databricks.example_databricks_sensors": [[18, 1, 1, "", "DAG_ID"], [18, 1, 1, "", "ENV_ID"], [18, 1, 1, "", "connection_id"], [18, 1, 1, "", "test_run"]], "tests.system.providers.databricks.example_databricks_sql": [[19, 1, 1, "", "DAG_ID"], [19, 1, 1, "", "ENV_ID"], [19, 1, 1, "", "connection_id"], [19, 1, 1, "", "test_run"]]}, "objtypes": {"0": "py:module", "1": "py:data", "2": "py:class", "3": "py:attribute", "4": "py:method", "5": "py:property", "6": "py:function"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "data", "Python data"], "2": ["py", "class", "Python class"], "3": ["py", "attribute", "Python attribute"], "4": ["py", "method", "Python method"], "5": ["py", "property", "Python property"], "6": ["py", "function", "Python function"]}, "titleterms": {"airflow": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 22, 24], "provid": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 24], "databrick": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 27, 29, 30, 31], "hook": [0, 1, 2, 3], "modul": [0, 1, 2, 5, 6, 7, 9, 10, 12, 14, 16, 17, 18, 19], "content": [0, 1, 2, 4, 5, 6, 7, 9, 10, 12, 14, 16, 17, 18, 19], "class": [0, 1, 2, 5, 6, 7, 9, 10, 12], "attribut": [0, 1, 2, 5, 7], "databricks_bas": 1, "databricks_sql": [2, 7, 10], "submodul": [3, 8, 11, 13, 15, 20], "subpackag": 4, "packag": [4, 22, 24, 25], "oper": [5, 6, 7, 8, 26, 27, 28, 29, 30, 31, 32, 33, 34], "databricks_repo": 6, "sensor": [9, 10, 11, 33], "databricks_partit": 9, "trigger": [12, 13], "util": [14, 15], "function": 14, "test": [16, 17, 18, 19, 20], "system": [16, 17, 18, 19, 20], "example_databrick": 16, "example_databricks_repo": 17, "example_databricks_sensor": 18, "example_databricks_sql": 19, "changelog": 21, "6": [21, 22], "3": [21, 22], "0": [21, 22], "featur": 21, "bug": 21, "fix": 21, "misc": 21, "2": [21, 22], "1": [21, 22], "break": 21, "chang": 21, "5": [21, 22], "yank": 21, "4": [21, 22], "7": [21, 22], "apach": [22, 24], "connect": 23, "authent": 23, "default": 23, "id": 23, "configur": 23, "instal": [24, 25], "requir": 24, "cross": 24, "depend": 24, "download": 24, "offici": 24, "from": [25, 33], "sourc": 25, "releas": [25, 35], "integr": 25, "verifi": 25, "pypi": 25, "databrickscopyintooper": 26, "us": [26, 28, 29, 30, 31, 32, 33, 34], "exampl": [26, 28, 29, 30, 31, 33, 34], "import": 26, "csv": 26, "data": [26, 33], "databrickscreatejobsoper": 28, "specifi": [28, 30, 31, 34], "paramet": [28, 34], "json": [28, 34], "name": [28, 34], "pair": 28, "databricksrunnowoper": [28, 32], "databricksreposcreateoper": 29, "creat": 29, "repo": [29, 30, 31], "databricksreposdeleteoper": 30, "delet": 30, "path": [30, 31], "databricksreposupdateoper": 31, "updat": 31, "databricksrunnowdeferrableoper": 32, "databrickssqloper": 33, "select": 33, "file": 33, "execut": 33, "multipl": 33, "statement": 33, "databrickssqlsensor": 33, "databrickspartitionsensor": 33, "databrickssubmitrunoper": 34, "databrickssubmitrundeferrableoper": 34, "secur": 35, "patch": 35}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.viewcode": 1, "sphinx.ext.intersphinx": 1, "sphinx": 57}, "alltitles": {"Databricks Connection": [[23, "databricks-connection"]], "Authenticating to Databricks": [[23, "authenticating-to-databricks"]], "Default Connection IDs": [[23, "default-connection-ids"]], "Configuring the Connection": [[23, "configuring-the-connection"]], "apache-airflow-providers-databricks": [[24, "apache-airflow-providers-databricks"]], "apache-airflow-providers-databricks package": [[24, "apache-airflow-providers-databricks-package"]], "Provider package": [[24, "provider-package"]], "Installation": [[24, "installation"]], "Requirements": [[24, "requirements"]], "Cross provider package dependencies": [[24, "cross-provider-package-dependencies"]], "Downloading official packages": [[24, "downloading-official-packages"]], "Installing from sources": [[25, "installing-from-sources"]], "Released packages": [[25, "released-packages"]], "Release integrity": [[25, "release-integrity"]], "Verifying PyPI releases": [[25, "verifying-pypi-releases"]], "DatabricksCopyIntoOperator": [[26, "databrickscopyintooperator"]], "Using the Operator": [[26, "using-the-operator"], [28, "using-the-operator"], [29, "using-the-operator"], [30, "using-the-operator"], [31, "using-the-operator"], [32, "using-the-operator"], [33, "using-the-operator"], [34, "using-the-operator"]], "Examples": [[26, "examples"], [28, "examples"], [29, "examples"], [30, "examples"], [31, "examples"], [33, "examples"], [33, "id1"], [33, "id3"], [34, "examples"]], "Importing CSV data": [[26, "importing-csv-data"]], "Databricks Operators": [[27, "databricks-operators"]], "DatabricksCreateJobsOperator": [[28, "databrickscreatejobsoperator"]], "Specifying parameters as JSON": [[28, "specifying-parameters-as-json"], [34, "specifying-parameters-as-json"]], "Using named parameters": [[28, "using-named-parameters"], [34, "using-named-parameters"]], "Pairing with DatabricksRunNowOperator": [[28, "pairing-with-databricksrunnowoperator"]], "DatabricksReposCreateOperator": [[29, "databricksreposcreateoperator"]], "Create a Databricks Repo": [[29, "create-a-databricks-repo"]], "DatabricksReposDeleteOperator": [[30, "databricksreposdeleteoperator"]], "Deleting Databricks Repo by specifying path": [[30, "deleting-databricks-repo-by-specifying-path"]], "DatabricksReposUpdateOperator": [[31, "databricksreposupdateoperator"]], "Updating Databricks Repo by specifying path": [[31, "updating-databricks-repo-by-specifying-path"]], "DatabricksRunNowOperator": [[32, "databricksrunnowoperator"]], "DatabricksRunNowDeferrableOperator": [[32, "databricksrunnowdeferrableoperator"]], "DatabricksSqlOperator": [[33, "databrickssqloperator"]], "Selecting data": [[33, "selecting-data"]], "Selecting data into a file": [[33, "selecting-data-into-a-file"]], "Executing multiple statements": [[33, "executing-multiple-statements"]], "Executing multiple statements from a file": [[33, "executing-multiple-statements-from-a-file"]], "DatabricksSqlSensor": [[33, "databrickssqlsensor"]], "Using the Sensor": [[33, "using-the-sensor"], [33, "id2"]], "DatabricksPartitionSensor": [[33, "databrickspartitionsensor"]], "DatabricksSubmitRunOperator": [[34, "databrickssubmitrunoperator"]], "DatabricksSubmitRunDeferrableOperator": [[34, "databrickssubmitrundeferrableoperator"]], "Releasing security patches": [[35, "releasing-security-patches"]], "airflow.providers.databricks.hooks.databricks": [[0, "module-airflow.providers.databricks.hooks.databricks"]], "Module Contents": [[0, "module-contents"], [1, "module-contents"], [2, "module-contents"], [5, "module-contents"], [6, "module-contents"], [7, "module-contents"], [9, "module-contents"], [10, "module-contents"], [12, "module-contents"], [14, "module-contents"], [16, "module-contents"], [17, "module-contents"], [18, "module-contents"], [19, "module-contents"]], "Classes": [[0, "classes"], [1, "classes"], [2, "classes"], [5, "classes"], [6, "classes"], [7, "classes"], [9, "classes"], [10, "classes"], [12, "classes"]], "Attributes": [[0, "attributes"], [1, "attributes"], [2, "attributes"], [5, "attributes"], [7, "attributes"]], "airflow.providers.databricks.hooks.databricks_base": [[1, "module-airflow.providers.databricks.hooks.databricks_base"]], "airflow.providers.databricks.hooks.databricks_sql": [[2, "module-airflow.providers.databricks.hooks.databricks_sql"]], "airflow.providers.databricks.hooks": [[3, "module-airflow.providers.databricks.hooks"]], "Submodules": [[3, "submodules"], [8, "submodules"], [11, "submodules"], [13, "submodules"], [15, "submodules"], [20, "submodules"]], "airflow.providers.databricks": [[4, "module-airflow.providers.databricks"]], "Subpackages": [[4, "subpackages"]], "Package Contents": [[4, "package-contents"]], "airflow.providers.databricks.operators.databricks": [[5, "module-airflow.providers.databricks.operators.databricks"]], "airflow.providers.databricks.operators.databricks_repos": [[6, "module-airflow.providers.databricks.operators.databricks_repos"]], "airflow.providers.databricks.operators.databricks_sql": [[7, "module-airflow.providers.databricks.operators.databricks_sql"]], "airflow.providers.databricks.operators": [[8, "module-airflow.providers.databricks.operators"]], "airflow.providers.databricks.sensors.databricks_partition": [[9, "module-airflow.providers.databricks.sensors.databricks_partition"]], "airflow.providers.databricks.sensors.databricks_sql": [[10, "module-airflow.providers.databricks.sensors.databricks_sql"]], "airflow.providers.databricks.sensors": [[11, "module-airflow.providers.databricks.sensors"]], "airflow.providers.databricks.triggers.databricks": [[12, "module-airflow.providers.databricks.triggers.databricks"]], "airflow.providers.databricks.triggers": [[13, "module-airflow.providers.databricks.triggers"]], "airflow.providers.databricks.utils.databricks": [[14, "module-airflow.providers.databricks.utils.databricks"]], "Functions": [[14, "functions"]], "airflow.providers.databricks.utils": [[15, "module-airflow.providers.databricks.utils"]], "tests.system.providers.databricks.example_databricks": [[16, "module-tests.system.providers.databricks.example_databricks"]], "tests.system.providers.databricks.example_databricks_repos": [[17, "module-tests.system.providers.databricks.example_databricks_repos"]], "tests.system.providers.databricks.example_databricks_sensors": [[18, "module-tests.system.providers.databricks.example_databricks_sensors"]], "tests.system.providers.databricks.example_databricks_sql": [[19, "module-tests.system.providers.databricks.example_databricks_sql"]], "tests.system.providers.databricks": [[20, "module-tests.system.providers.databricks"]], "Changelog": [[21, "changelog"]], "6.3.0": [[21, "id1"], [22, "id1"]], "Features": [[21, "features"], [21, "id3"], [21, "id6"], [21, "id15"], [21, "id18"], [21, "id22"], [21, "id25"], [21, "id36"], [21, "id41"], [21, "id44"], [21, "id53"], [21, "id55"], [21, "id59"], [21, "id62"], [21, "id67"], [21, "id70"], [21, "id72"], [21, "id76"], [21, "id79"], [21, "id82"], [21, "id86"], [21, "id88"]], "Bug Fixes": [[21, "bug-fixes"], [21, "id7"], [21, "id9"], [21, "id19"], [21, "id30"], [21, "id33"], [21, "id37"], [21, "id46"], [21, "id49"], [21, "id57"], [21, "id60"], [21, "id63"], [21, "id68"], [21, "id73"], [21, "id77"], [21, "id83"], [21, "id89"], [21, "id91"]], "Misc": [[21, "misc"], [21, "id4"], [21, "id10"], [21, "id11"], [21, "id20"], [21, "id23"], [21, "id26"], [21, "id28"], [21, "id31"], [21, "id34"], [21, "id38"], [21, "id42"], [21, "id52"], [21, "id56"], [21, "id74"], [21, "id80"], [21, "id84"], [21, "id93"]], "6.2.0": [[21, "id2"], [22, "id2"]], "6.1.0": [[21, "id5"], [22, "id3"]], "6.0.0": [[21, "id8"], [22, "id4"]], "Breaking changes": [[21, "breaking-changes"], [21, "id13"], [21, "id48"], [21, "id65"], [21, "id95"]], "5.0.1 (YANKED)": [[21, "yanked"]], "5.0.0": [[21, "id12"], [22, "id6"]], "4.7.0": [[21, "id14"], [22, "id7"]], "4.6.0": [[21, "id16"], [22, "id8"]], "4.5.0": [[21, "id21"], [22, "id9"]], "4.4.0": [[21, "id24"], [22, "id10"]], "4.3.3": [[21, "id27"], [22, "id11"]], "4.3.2": [[21, "id29"], [22, "id13"]], "4.3.1": [[21, "id32"], [22, "id14"]], "4.3.0": [[21, "id35"], [22, "id15"]], "4.2.0": [[21, "id39"], [22, "id16"]], "4.1.0": [[21, "id43"], [22, "id18"]], "4.0.1": [[21, "id45"], [22, "id19"]], "4.0.0": [[21, "id47"], [22, "id20"]], "3.4.0 (YANKED)": [[21, "id50"]], "3.3.0": [[21, "id54"], [22, "id22"]], "3.2.0": [[21, "id58"], [22, "id24"]], "3.1.0": [[21, "id61"], [22, "id26"]], "3.0.0": [[21, "id64"], [22, "id27"]], "2.7.0": [[21, "id69"], [22, "id28"]], "2.6.0": [[21, "id71"], [22, "id29"]], "2.5.0": [[21, "id75"], [22, "id30"]], "2.4.0": [[21, "id78"], [22, "id31"]], "2.3.0": [[21, "id81"], [22, "id33"]], "2.2.0": [[21, "id85"], [22, "id34"]], "2.1.0": [[21, "id87"], [22, "id35"]], "2.0.2": [[21, "id90"], [22, "id36"]], "2.0.1": [[21, "id92"], [22, "id37"]], "2.0.0": [[21, "id94"], [22, "id38"]], "1.0.1": [[21, "id96"], [22, "id39"]], "1.0.0": [[21, "id97"], [22, "id40"]], "Package apache-airflow-providers-databricks": [[22, "package-apache-airflow-providers-databricks"]], "5.0.1": [[22, "id5"]], "3.4.0": [[22, "id21"]]}, "indexentries": {"cancel_all_runs_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.CANCEL_ALL_RUNS_ENDPOINT"]], "cancel_run_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.CANCEL_RUN_ENDPOINT"]], "cluster_life_cycle_states (airflow.providers.databricks.hooks.databricks.clusterstate attribute)": [[0, "airflow.providers.databricks.hooks.databricks.ClusterState.CLUSTER_LIFE_CYCLE_STATES"]], "create_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.CREATE_ENDPOINT"]], "clusterstate (class in airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.ClusterState"]], "delete_run_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.DELETE_RUN_ENDPOINT"]], "databrickshook (class in airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook"]], "get_cluster_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.GET_CLUSTER_ENDPOINT"]], "get_run_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.GET_RUN_ENDPOINT"]], "install_libs_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.INSTALL_LIBS_ENDPOINT"]], "list_jobs_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.LIST_JOBS_ENDPOINT"]], "list_pipelines_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.LIST_PIPELINES_ENDPOINT"]], "output_runs_job_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.OUTPUT_RUNS_JOB_ENDPOINT"]], "repair_run_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.REPAIR_RUN_ENDPOINT"]], "reset_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.RESET_ENDPOINT"]], "restart_cluster_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.RESTART_CLUSTER_ENDPOINT"]], "run_life_cycle_states (airflow.providers.databricks.hooks.databricks.runstate attribute)": [[0, "airflow.providers.databricks.hooks.databricks.RunState.RUN_LIFE_CYCLE_STATES"]], "run_now_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.RUN_NOW_ENDPOINT"]], "runstate (class in airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.RunState"]], "spark_versions_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.SPARK_VERSIONS_ENDPOINT"]], "start_cluster_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.START_CLUSTER_ENDPOINT"]], "submit_run_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.SUBMIT_RUN_ENDPOINT"]], "terminate_cluster_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.TERMINATE_CLUSTER_ENDPOINT"]], "uninstall_libs_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.UNINSTALL_LIBS_ENDPOINT"]], "workspace_get_status_endpoint (in module airflow.providers.databricks.hooks.databricks)": [[0, "airflow.providers.databricks.hooks.databricks.WORKSPACE_GET_STATUS_ENDPOINT"]], "__eq__() (airflow.providers.databricks.hooks.databricks.clusterstate method)": [[0, "airflow.providers.databricks.hooks.databricks.ClusterState.__eq__"]], "__eq__() (airflow.providers.databricks.hooks.databricks.runstate method)": [[0, "airflow.providers.databricks.hooks.databricks.RunState.__eq__"]], "__repr__() (airflow.providers.databricks.hooks.databricks.clusterstate method)": [[0, "airflow.providers.databricks.hooks.databricks.ClusterState.__repr__"]], "__repr__() (airflow.providers.databricks.hooks.databricks.runstate method)": [[0, "airflow.providers.databricks.hooks.databricks.RunState.__repr__"]], "a_get_cluster_state() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.a_get_cluster_state"]], "a_get_run() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.a_get_run"]], "a_get_run_page_url() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.a_get_run_page_url"]], "a_get_run_state() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.a_get_run_state"]], "airflow.providers.databricks.hooks.databricks": [[0, "module-airflow.providers.databricks.hooks.databricks"]], "cancel_all_runs() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.cancel_all_runs"]], "cancel_run() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.cancel_run"]], "create_job() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.create_job"]], "create_repo() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.create_repo"]], "delete_repo() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.delete_repo"]], "delete_run() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.delete_run"]], "find_job_id_by_name() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.find_job_id_by_name"]], "find_pipeline_id_by_name() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.find_pipeline_id_by_name"]], "from_json() (airflow.providers.databricks.hooks.databricks.clusterstate class method)": [[0, "airflow.providers.databricks.hooks.databricks.ClusterState.from_json"]], "from_json() (airflow.providers.databricks.hooks.databricks.runstate class method)": [[0, "airflow.providers.databricks.hooks.databricks.RunState.from_json"]], "get_cluster_state() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.get_cluster_state"]], "get_job_id() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.get_job_id"]], "get_latest_repair_id() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.get_latest_repair_id"]], "get_repo_by_path() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.get_repo_by_path"]], "get_run() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.get_run"]], "get_run_output() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.get_run_output"]], "get_run_page_url() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.get_run_page_url"]], "get_run_state() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.get_run_state"]], "get_run_state_lifecycle() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.get_run_state_lifecycle"]], "get_run_state_message() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.get_run_state_message"]], "get_run_state_result() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.get_run_state_result"]], "get_run_state_str() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.get_run_state_str"]], "hook_name (airflow.providers.databricks.hooks.databricks.databrickshook attribute)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.hook_name"]], "install() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.install"]], "is_running (airflow.providers.databricks.hooks.databricks.clusterstate property)": [[0, "airflow.providers.databricks.hooks.databricks.ClusterState.is_running"]], "is_successful (airflow.providers.databricks.hooks.databricks.runstate property)": [[0, "airflow.providers.databricks.hooks.databricks.RunState.is_successful"]], "is_terminal (airflow.providers.databricks.hooks.databricks.clusterstate property)": [[0, "airflow.providers.databricks.hooks.databricks.ClusterState.is_terminal"]], "is_terminal (airflow.providers.databricks.hooks.databricks.runstate property)": [[0, "airflow.providers.databricks.hooks.databricks.RunState.is_terminal"]], "list_jobs() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.list_jobs"]], "list_pipelines() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.list_pipelines"]], "module": [[0, "module-airflow.providers.databricks.hooks.databricks"], [1, "module-airflow.providers.databricks.hooks.databricks_base"], [2, "module-airflow.providers.databricks.hooks.databricks_sql"], [3, "module-airflow.providers.databricks.hooks"], [4, "module-airflow.providers.databricks"], [5, "module-airflow.providers.databricks.operators.databricks"], [6, "module-airflow.providers.databricks.operators.databricks_repos"], [7, "module-airflow.providers.databricks.operators.databricks_sql"], [8, "module-airflow.providers.databricks.operators"], [9, "module-airflow.providers.databricks.sensors.databricks_partition"], [10, "module-airflow.providers.databricks.sensors.databricks_sql"], [11, "module-airflow.providers.databricks.sensors"], [12, "module-airflow.providers.databricks.triggers.databricks"], [13, "module-airflow.providers.databricks.triggers"], [14, "module-airflow.providers.databricks.utils.databricks"], [15, "module-airflow.providers.databricks.utils"], [16, "module-tests.system.providers.databricks.example_databricks"], [17, "module-tests.system.providers.databricks.example_databricks_repos"], [18, "module-tests.system.providers.databricks.example_databricks_sensors"], [19, "module-tests.system.providers.databricks.example_databricks_sql"], [20, "module-tests.system.providers.databricks"]], "repair_run() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.repair_run"]], "reset_job() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.reset_job"]], "restart_cluster() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.restart_cluster"]], "run_now() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.run_now"]], "start_cluster() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.start_cluster"]], "submit_run() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.submit_run"]], "terminate_cluster() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.terminate_cluster"]], "test_connection() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.test_connection"]], "to_json() (airflow.providers.databricks.hooks.databricks.clusterstate method)": [[0, "airflow.providers.databricks.hooks.databricks.ClusterState.to_json"]], "to_json() (airflow.providers.databricks.hooks.databricks.runstate method)": [[0, "airflow.providers.databricks.hooks.databricks.RunState.to_json"]], "uninstall() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.uninstall"]], "update_job_permission() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.update_job_permission"]], "update_repo() (airflow.providers.databricks.hooks.databricks.databrickshook method)": [[0, "airflow.providers.databricks.hooks.databricks.DatabricksHook.update_repo"]], "azure_default_ad_endpoint (in module airflow.providers.databricks.hooks.databricks_base)": [[1, "airflow.providers.databricks.hooks.databricks_base.AZURE_DEFAULT_AD_ENDPOINT"]], "azure_management_endpoint (in module airflow.providers.databricks.hooks.databricks_base)": [[1, "airflow.providers.databricks.hooks.databricks_base.AZURE_MANAGEMENT_ENDPOINT"]], "azure_metadata_service_instance_url (in module airflow.providers.databricks.hooks.databricks_base)": [[1, "airflow.providers.databricks.hooks.databricks_base.AZURE_METADATA_SERVICE_INSTANCE_URL"]], "azure_metadata_service_token_url (in module airflow.providers.databricks.hooks.databricks_base)": [[1, "airflow.providers.databricks.hooks.databricks_base.AZURE_METADATA_SERVICE_TOKEN_URL"]], "azure_token_service_url (in module airflow.providers.databricks.hooks.databricks_base)": [[1, "airflow.providers.databricks.hooks.databricks_base.AZURE_TOKEN_SERVICE_URL"]], "basedatabrickshook (class in airflow.providers.databricks.hooks.databricks_base)": [[1, "airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook"]], "bearerauth (class in airflow.providers.databricks.hooks.databricks_base)": [[1, "airflow.providers.databricks.hooks.databricks_base.BearerAuth"]], "default_databricks_scope (in module airflow.providers.databricks.hooks.databricks_base)": [[1, "airflow.providers.databricks.hooks.databricks_base.DEFAULT_DATABRICKS_SCOPE"]], "oidc_token_service_url (in module airflow.providers.databricks.hooks.databricks_base)": [[1, "airflow.providers.databricks.hooks.databricks_base.OIDC_TOKEN_SERVICE_URL"]], "token_refresh_lead_time (in module airflow.providers.databricks.hooks.databricks_base)": [[1, "airflow.providers.databricks.hooks.databricks_base.TOKEN_REFRESH_LEAD_TIME"]], "__aenter__() (airflow.providers.databricks.hooks.databricks_base.basedatabrickshook method)": [[1, "airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook.__aenter__"]], "__aexit__() (airflow.providers.databricks.hooks.databricks_base.basedatabrickshook method)": [[1, "airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook.__aexit__"]], "airflow.providers.databricks.hooks.databricks_base": [[1, "module-airflow.providers.databricks.hooks.databricks_base"]], "conn_name_attr (airflow.providers.databricks.hooks.databricks_base.basedatabrickshook attribute)": [[1, "airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook.conn_name_attr"]], "conn_type (airflow.providers.databricks.hooks.databricks_base.basedatabrickshook attribute)": [[1, "airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook.conn_type"]], "databricks_conn() (airflow.providers.databricks.hooks.databricks_base.basedatabrickshook method)": [[1, "airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook.databricks_conn"]], "default_conn_name (airflow.providers.databricks.hooks.databricks_base.basedatabrickshook attribute)": [[1, "airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook.default_conn_name"]], "encode() (airflow.providers.databricks.hooks.databricks_base.bearerauth method)": [[1, "airflow.providers.databricks.hooks.databricks_base.BearerAuth.encode"]], "extra_parameters (airflow.providers.databricks.hooks.databricks_base.basedatabrickshook attribute)": [[1, "airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook.extra_parameters"]], "get_conn() (airflow.providers.databricks.hooks.databricks_base.basedatabrickshook method)": [[1, "airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook.get_conn"]], "host() (airflow.providers.databricks.hooks.databricks_base.basedatabrickshook method)": [[1, "airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook.host"]], "user_agent_header() (airflow.providers.databricks.hooks.databricks_base.basedatabrickshook method)": [[1, "airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook.user_agent_header"]], "user_agent_value() (airflow.providers.databricks.hooks.databricks_base.basedatabrickshook method)": [[1, "airflow.providers.databricks.hooks.databricks_base.BaseDatabricksHook.user_agent_value"]], "databrickssqlhook (class in airflow.providers.databricks.hooks.databricks_sql)": [[2, "airflow.providers.databricks.hooks.databricks_sql.DatabricksSqlHook"]], "list_sql_endpoints_endpoint (in module airflow.providers.databricks.hooks.databricks_sql)": [[2, "airflow.providers.databricks.hooks.databricks_sql.LIST_SQL_ENDPOINTS_ENDPOINT"]], "t (in module airflow.providers.databricks.hooks.databricks_sql)": [[2, "airflow.providers.databricks.hooks.databricks_sql.T"]], "airflow.providers.databricks.hooks.databricks_sql": [[2, "module-airflow.providers.databricks.hooks.databricks_sql"]], "bulk_dump() (airflow.providers.databricks.hooks.databricks_sql.databrickssqlhook method)": [[2, "airflow.providers.databricks.hooks.databricks_sql.DatabricksSqlHook.bulk_dump"]], "bulk_load() (airflow.providers.databricks.hooks.databricks_sql.databrickssqlhook method)": [[2, "airflow.providers.databricks.hooks.databricks_sql.DatabricksSqlHook.bulk_load"]], "get_conn() (airflow.providers.databricks.hooks.databricks_sql.databrickssqlhook method)": [[2, "airflow.providers.databricks.hooks.databricks_sql.DatabricksSqlHook.get_conn"]], "hook_name (airflow.providers.databricks.hooks.databricks_sql.databrickssqlhook attribute)": [[2, "airflow.providers.databricks.hooks.databricks_sql.DatabricksSqlHook.hook_name"]], "run() (airflow.providers.databricks.hooks.databricks_sql.databrickssqlhook method)": [[2, "airflow.providers.databricks.hooks.databricks_sql.DatabricksSqlHook.run"]], "airflow.providers.databricks.hooks": [[3, "module-airflow.providers.databricks.hooks"]], "__version__ (in module airflow.providers.databricks)": [[4, "airflow.providers.databricks.__version__"]], "airflow.providers.databricks": [[4, "module-airflow.providers.databricks"]], "defer_method_name (in module airflow.providers.databricks.operators.databricks)": [[5, "airflow.providers.databricks.operators.databricks.DEFER_METHOD_NAME"]], "databrickscreatejobsoperator (class in airflow.providers.databricks.operators.databricks)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksCreateJobsOperator"]], "databricksjobrunlink (class in airflow.providers.databricks.operators.databricks)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksJobRunLink"]], "databricksrunnowdeferrableoperator (class in airflow.providers.databricks.operators.databricks)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksRunNowDeferrableOperator"]], "databricksrunnowoperator (class in airflow.providers.databricks.operators.databricks)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksRunNowOperator"]], "databrickssubmitrundeferrableoperator (class in airflow.providers.databricks.operators.databricks)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksSubmitRunDeferrableOperator"]], "databrickssubmitrunoperator (class in airflow.providers.databricks.operators.databricks)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksSubmitRunOperator"]], "xcom_job_id_key (in module airflow.providers.databricks.operators.databricks)": [[5, "airflow.providers.databricks.operators.databricks.XCOM_JOB_ID_KEY"]], "xcom_run_id_key (in module airflow.providers.databricks.operators.databricks)": [[5, "airflow.providers.databricks.operators.databricks.XCOM_RUN_ID_KEY"]], "xcom_run_page_url_key (in module airflow.providers.databricks.operators.databricks)": [[5, "airflow.providers.databricks.operators.databricks.XCOM_RUN_PAGE_URL_KEY"]], "airflow.providers.databricks.operators.databricks": [[5, "module-airflow.providers.databricks.operators.databricks"]], "execute() (airflow.providers.databricks.operators.databricks.databrickscreatejobsoperator method)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksCreateJobsOperator.execute"]], "execute() (airflow.providers.databricks.operators.databricks.databricksrunnowoperator method)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksRunNowOperator.execute"]], "execute() (airflow.providers.databricks.operators.databricks.databrickssubmitrundeferrableoperator method)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksSubmitRunDeferrableOperator.execute"]], "execute() (airflow.providers.databricks.operators.databricks.databrickssubmitrunoperator method)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksSubmitRunOperator.execute"]], "execute_complete() (airflow.providers.databricks.operators.databricks.databricksrunnowoperator method)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksRunNowOperator.execute_complete"]], "execute_complete() (airflow.providers.databricks.operators.databricks.databrickssubmitrunoperator method)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksSubmitRunOperator.execute_complete"]], "get_link() (airflow.providers.databricks.operators.databricks.databricksjobrunlink method)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksJobRunLink.get_link"]], "name (airflow.providers.databricks.operators.databricks.databricksjobrunlink attribute)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksJobRunLink.name"]], "on_kill() (airflow.providers.databricks.operators.databricks.databricksrunnowoperator method)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksRunNowOperator.on_kill"]], "on_kill() (airflow.providers.databricks.operators.databricks.databrickssubmitrunoperator method)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksSubmitRunOperator.on_kill"]], "operator_extra_links (airflow.providers.databricks.operators.databricks.databricksrunnowoperator attribute)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksRunNowOperator.operator_extra_links"]], "operator_extra_links (airflow.providers.databricks.operators.databricks.databrickssubmitrunoperator attribute)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksSubmitRunOperator.operator_extra_links"]], "template_ext (airflow.providers.databricks.operators.databricks.databricksrunnowoperator attribute)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksRunNowOperator.template_ext"]], "template_ext (airflow.providers.databricks.operators.databricks.databrickssubmitrunoperator attribute)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksSubmitRunOperator.template_ext"]], "template_fields (airflow.providers.databricks.operators.databricks.databrickscreatejobsoperator attribute)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksCreateJobsOperator.template_fields"]], "template_fields (airflow.providers.databricks.operators.databricks.databricksrunnowoperator attribute)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksRunNowOperator.template_fields"]], "template_fields (airflow.providers.databricks.operators.databricks.databrickssubmitrunoperator attribute)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksSubmitRunOperator.template_fields"]], "ui_color (airflow.providers.databricks.operators.databricks.databrickscreatejobsoperator attribute)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksCreateJobsOperator.ui_color"]], "ui_color (airflow.providers.databricks.operators.databricks.databricksrunnowoperator attribute)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksRunNowOperator.ui_color"]], "ui_color (airflow.providers.databricks.operators.databricks.databrickssubmitrunoperator attribute)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksSubmitRunOperator.ui_color"]], "ui_fgcolor (airflow.providers.databricks.operators.databricks.databrickscreatejobsoperator attribute)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksCreateJobsOperator.ui_fgcolor"]], "ui_fgcolor (airflow.providers.databricks.operators.databricks.databricksrunnowoperator attribute)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksRunNowOperator.ui_fgcolor"]], "ui_fgcolor (airflow.providers.databricks.operators.databricks.databrickssubmitrunoperator attribute)": [[5, "airflow.providers.databricks.operators.databricks.DatabricksSubmitRunOperator.ui_fgcolor"]], "databricksreposcreateoperator (class in airflow.providers.databricks.operators.databricks_repos)": [[6, "airflow.providers.databricks.operators.databricks_repos.DatabricksReposCreateOperator"]], "databricksreposdeleteoperator (class in airflow.providers.databricks.operators.databricks_repos)": [[6, "airflow.providers.databricks.operators.databricks_repos.DatabricksReposDeleteOperator"]], "databricksreposupdateoperator (class in airflow.providers.databricks.operators.databricks_repos)": [[6, "airflow.providers.databricks.operators.databricks_repos.DatabricksReposUpdateOperator"]], "__aws_code_commit_regexp__ (airflow.providers.databricks.operators.databricks_repos.databricksreposcreateoperator attribute)": [[6, "airflow.providers.databricks.operators.databricks_repos.DatabricksReposCreateOperator.__aws_code_commit_regexp__"]], "__detect_repo_provider__() (airflow.providers.databricks.operators.databricks_repos.databricksreposcreateoperator static method)": [[6, "airflow.providers.databricks.operators.databricks_repos.DatabricksReposCreateOperator.__detect_repo_provider__"]], "__git_providers__ (airflow.providers.databricks.operators.databricks_repos.databricksreposcreateoperator attribute)": [[6, "airflow.providers.databricks.operators.databricks_repos.DatabricksReposCreateOperator.__git_providers__"]], "__repos_path_regexp__ (airflow.providers.databricks.operators.databricks_repos.databricksreposcreateoperator attribute)": [[6, "airflow.providers.databricks.operators.databricks_repos.DatabricksReposCreateOperator.__repos_path_regexp__"]], "airflow.providers.databricks.operators.databricks_repos": [[6, "module-airflow.providers.databricks.operators.databricks_repos"]], "execute() (airflow.providers.databricks.operators.databricks_repos.databricksreposcreateoperator method)": [[6, "airflow.providers.databricks.operators.databricks_repos.DatabricksReposCreateOperator.execute"]], "execute() (airflow.providers.databricks.operators.databricks_repos.databricksreposdeleteoperator method)": [[6, "airflow.providers.databricks.operators.databricks_repos.DatabricksReposDeleteOperator.execute"]], "execute() (airflow.providers.databricks.operators.databricks_repos.databricksreposupdateoperator method)": [[6, "airflow.providers.databricks.operators.databricks_repos.DatabricksReposUpdateOperator.execute"]], "template_fields (airflow.providers.databricks.operators.databricks_repos.databricksreposcreateoperator attribute)": [[6, "airflow.providers.databricks.operators.databricks_repos.DatabricksReposCreateOperator.template_fields"]], "template_fields (airflow.providers.databricks.operators.databricks_repos.databricksreposdeleteoperator attribute)": [[6, "airflow.providers.databricks.operators.databricks_repos.DatabricksReposDeleteOperator.template_fields"]], "template_fields (airflow.providers.databricks.operators.databricks_repos.databricksreposupdateoperator attribute)": [[6, "airflow.providers.databricks.operators.databricks_repos.DatabricksReposUpdateOperator.template_fields"]], "copy_into_approved_formats (in module airflow.providers.databricks.operators.databricks_sql)": [[7, "airflow.providers.databricks.operators.databricks_sql.COPY_INTO_APPROVED_FORMATS"]], "databrickscopyintooperator (class in airflow.providers.databricks.operators.databricks_sql)": [[7, "airflow.providers.databricks.operators.databricks_sql.DatabricksCopyIntoOperator"]], "databrickssqloperator (class in airflow.providers.databricks.operators.databricks_sql)": [[7, "airflow.providers.databricks.operators.databricks_sql.DatabricksSqlOperator"]], "airflow.providers.databricks.operators.databricks_sql": [[7, "module-airflow.providers.databricks.operators.databricks_sql"]], "conn_id_field (airflow.providers.databricks.operators.databricks_sql.databrickssqloperator attribute)": [[7, "airflow.providers.databricks.operators.databricks_sql.DatabricksSqlOperator.conn_id_field"]], "execute() (airflow.providers.databricks.operators.databricks_sql.databrickscopyintooperator method)": [[7, "airflow.providers.databricks.operators.databricks_sql.DatabricksCopyIntoOperator.execute"]], "get_db_hook() (airflow.providers.databricks.operators.databricks_sql.databrickssqloperator method)": [[7, "airflow.providers.databricks.operators.databricks_sql.DatabricksSqlOperator.get_db_hook"]], "template_ext (airflow.providers.databricks.operators.databricks_sql.databrickssqloperator attribute)": [[7, "airflow.providers.databricks.operators.databricks_sql.DatabricksSqlOperator.template_ext"]], "template_fields (airflow.providers.databricks.operators.databricks_sql.databrickscopyintooperator attribute)": [[7, "airflow.providers.databricks.operators.databricks_sql.DatabricksCopyIntoOperator.template_fields"]], "template_fields (airflow.providers.databricks.operators.databricks_sql.databrickssqloperator attribute)": [[7, "airflow.providers.databricks.operators.databricks_sql.DatabricksSqlOperator.template_fields"]], "template_fields_renderers (airflow.providers.databricks.operators.databricks_sql.databrickssqloperator attribute)": [[7, "airflow.providers.databricks.operators.databricks_sql.DatabricksSqlOperator.template_fields_renderers"]], "airflow.providers.databricks.operators": [[8, "module-airflow.providers.databricks.operators"]], "databrickspartitionsensor (class in airflow.providers.databricks.sensors.databricks_partition)": [[9, "airflow.providers.databricks.sensors.databricks_partition.DatabricksPartitionSensor"]], "airflow.providers.databricks.sensors.databricks_partition": [[9, "module-airflow.providers.databricks.sensors.databricks_partition"]], "poke() (airflow.providers.databricks.sensors.databricks_partition.databrickspartitionsensor method)": [[9, "airflow.providers.databricks.sensors.databricks_partition.DatabricksPartitionSensor.poke"]], "template_ext (airflow.providers.databricks.sensors.databricks_partition.databrickspartitionsensor attribute)": [[9, "airflow.providers.databricks.sensors.databricks_partition.DatabricksPartitionSensor.template_ext"]], "template_fields (airflow.providers.databricks.sensors.databricks_partition.databrickspartitionsensor attribute)": [[9, "airflow.providers.databricks.sensors.databricks_partition.DatabricksPartitionSensor.template_fields"]], "template_fields_renderers (airflow.providers.databricks.sensors.databricks_partition.databrickspartitionsensor attribute)": [[9, "airflow.providers.databricks.sensors.databricks_partition.DatabricksPartitionSensor.template_fields_renderers"]], "databrickssqlsensor (class in airflow.providers.databricks.sensors.databricks_sql)": [[10, "airflow.providers.databricks.sensors.databricks_sql.DatabricksSqlSensor"]], "airflow.providers.databricks.sensors.databricks_sql": [[10, "module-airflow.providers.databricks.sensors.databricks_sql"]], "hook() (airflow.providers.databricks.sensors.databricks_sql.databrickssqlsensor method)": [[10, "airflow.providers.databricks.sensors.databricks_sql.DatabricksSqlSensor.hook"]], "poke() (airflow.providers.databricks.sensors.databricks_sql.databrickssqlsensor method)": [[10, "airflow.providers.databricks.sensors.databricks_sql.DatabricksSqlSensor.poke"]], "template_ext (airflow.providers.databricks.sensors.databricks_sql.databrickssqlsensor attribute)": [[10, "airflow.providers.databricks.sensors.databricks_sql.DatabricksSqlSensor.template_ext"]], "template_fields (airflow.providers.databricks.sensors.databricks_sql.databrickssqlsensor attribute)": [[10, "airflow.providers.databricks.sensors.databricks_sql.DatabricksSqlSensor.template_fields"]], "template_fields_renderers (airflow.providers.databricks.sensors.databricks_sql.databrickssqlsensor attribute)": [[10, "airflow.providers.databricks.sensors.databricks_sql.DatabricksSqlSensor.template_fields_renderers"]], "airflow.providers.databricks.sensors": [[11, "module-airflow.providers.databricks.sensors"]], "databricksexecutiontrigger (class in airflow.providers.databricks.triggers.databricks)": [[12, "airflow.providers.databricks.triggers.databricks.DatabricksExecutionTrigger"]], "airflow.providers.databricks.triggers.databricks": [[12, "module-airflow.providers.databricks.triggers.databricks"]], "run() (airflow.providers.databricks.triggers.databricks.databricksexecutiontrigger method)": [[12, "airflow.providers.databricks.triggers.databricks.DatabricksExecutionTrigger.run"]], "serialize() (airflow.providers.databricks.triggers.databricks.databricksexecutiontrigger method)": [[12, "airflow.providers.databricks.triggers.databricks.DatabricksExecutionTrigger.serialize"]], "airflow.providers.databricks.triggers": [[13, "module-airflow.providers.databricks.triggers"]], "airflow.providers.databricks.utils.databricks": [[14, "module-airflow.providers.databricks.utils.databricks"]], "normalise_json_content() (in module airflow.providers.databricks.utils.databricks)": [[14, "airflow.providers.databricks.utils.databricks.normalise_json_content"]], "validate_trigger_event() (in module airflow.providers.databricks.utils.databricks)": [[14, "airflow.providers.databricks.utils.databricks.validate_trigger_event"]], "airflow.providers.databricks.utils": [[15, "module-airflow.providers.databricks.utils"]], "dag_id (in module tests.system.providers.databricks.example_databricks)": [[16, "tests.system.providers.databricks.example_databricks.DAG_ID"]], "env_id (in module tests.system.providers.databricks.example_databricks)": [[16, "tests.system.providers.databricks.example_databricks.ENV_ID"]], "job (in module tests.system.providers.databricks.example_databricks)": [[16, "tests.system.providers.databricks.example_databricks.job"]], "test_run (in module tests.system.providers.databricks.example_databricks)": [[16, "tests.system.providers.databricks.example_databricks.test_run"]], "tests.system.providers.databricks.example_databricks": [[16, "module-tests.system.providers.databricks.example_databricks"]], "dag_id (in module tests.system.providers.databricks.example_databricks_repos)": [[17, "tests.system.providers.databricks.example_databricks_repos.DAG_ID"]], "env_id (in module tests.system.providers.databricks.example_databricks_repos)": [[17, "tests.system.providers.databricks.example_databricks_repos.ENV_ID"]], "default_args (in module tests.system.providers.databricks.example_databricks_repos)": [[17, "tests.system.providers.databricks.example_databricks_repos.default_args"]], "repo_path (in module tests.system.providers.databricks.example_databricks_repos)": [[17, "tests.system.providers.databricks.example_databricks_repos.repo_path"]], "test_run (in module tests.system.providers.databricks.example_databricks_repos)": [[17, "tests.system.providers.databricks.example_databricks_repos.test_run"]], "tests.system.providers.databricks.example_databricks_repos": [[17, "module-tests.system.providers.databricks.example_databricks_repos"]], "dag_id (in module tests.system.providers.databricks.example_databricks_sensors)": [[18, "tests.system.providers.databricks.example_databricks_sensors.DAG_ID"]], "env_id (in module tests.system.providers.databricks.example_databricks_sensors)": [[18, "tests.system.providers.databricks.example_databricks_sensors.ENV_ID"]], "connection_id (in module tests.system.providers.databricks.example_databricks_sensors)": [[18, "tests.system.providers.databricks.example_databricks_sensors.connection_id"]], "test_run (in module tests.system.providers.databricks.example_databricks_sensors)": [[18, "tests.system.providers.databricks.example_databricks_sensors.test_run"]], "tests.system.providers.databricks.example_databricks_sensors": [[18, "module-tests.system.providers.databricks.example_databricks_sensors"]], "dag_id (in module tests.system.providers.databricks.example_databricks_sql)": [[19, "tests.system.providers.databricks.example_databricks_sql.DAG_ID"]], "env_id (in module tests.system.providers.databricks.example_databricks_sql)": [[19, "tests.system.providers.databricks.example_databricks_sql.ENV_ID"]], "connection_id (in module tests.system.providers.databricks.example_databricks_sql)": [[19, "tests.system.providers.databricks.example_databricks_sql.connection_id"]], "test_run (in module tests.system.providers.databricks.example_databricks_sql)": [[19, "tests.system.providers.databricks.example_databricks_sql.test_run"]], "tests.system.providers.databricks.example_databricks_sql": [[19, "module-tests.system.providers.databricks.example_databricks_sql"]], "tests.system.providers.databricks": [[20, "module-tests.system.providers.databricks"]]}}) \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/6.3.0/security.html b/docs-archive/apache-airflow-providers-databricks/6.3.0/security.html new file mode 100644 index 00000000000..b5be9426b5e --- /dev/null +++ b/docs-archive/apache-airflow-providers-databricks/6.3.0/security.html @@ -0,0 +1,885 @@ + + + + + + + + + + + + Releasing security patches — apache-airflow-providers-databricks Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+
+
+

Releasing security patches

+

Airflow providers are released independently from Airflow itself and the information about vulnerabilities +is published separately. You can upgrade providers independently from Airflow itself, following the +instructions found in Installation from PyPI.

+

When we release Provider version, the development is always done from the main branch where we prepare +the next version. The provider uses strict SemVer versioning policy. Depending on +the scope of the change, Provider will get ''MAJOR'' version upgrade when there are +breaking changes, MINOR version upgrade when there are new features or PATCHLEVEL version upgrade +when there are only bug fixes (including security bugfixes) - and this is the only version that receives +security fixes by default, so you should upgrade to latest version of the provider if you want to receive +all released security fixes.

+

The only exception to that rule is when we have a critical security fix and good reason to provide an +out-of-band release for the provider, in which case stakeholders in the provider might decide to cherry-pick +and prepare a branch for an older version of the provider following the +mixed governance model +and requires interested parties to cherry-pick and test the fixes.

+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-databricks/stable.txt b/docs-archive/apache-airflow-providers-databricks/stable.txt index 6abaeb2f907..e7e42a4b585 100644 --- a/docs-archive/apache-airflow-providers-databricks/stable.txt +++ b/docs-archive/apache-airflow-providers-databricks/stable.txt @@ -1 +1 @@ -6.2.0 +6.3.0 \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/.buildinfo b/docs-archive/apache-airflow-providers-fab/1.0.4/.buildinfo new file mode 100644 index 00000000000..a6d010af426 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 2b6da7fbe5da49fa4412c99c110d475c +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/auth/backend/basic_auth/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/auth/backend/basic_auth/index.html new file mode 100644 index 00000000000..80aa5644877 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/auth/backend/basic_auth/index.html @@ -0,0 +1,963 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.api.auth.backend.basic_auth — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.api.auth.backend.basic_auth

+

Basic authentication backend.

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + + + + + + + +

init_app(_)

Initialize authentication backend.

auth_current_user()

Authenticate and set current user if Authorization header exists.

requires_authentication(function)

Decorate functions that require authentication.

+
+
+

Attributes

+ ++++ + + + + + + + + +

CLIENT_AUTH

T

+
+
+airflow.providers.fab.auth_manager.api.auth.backend.basic_auth.CLIENT_AUTH: tuple[str, str] | Any | None[source]
+
+ +
+
+airflow.providers.fab.auth_manager.api.auth.backend.basic_auth.T[source]
+
+ +
+
+airflow.providers.fab.auth_manager.api.auth.backend.basic_auth.init_app(_)[source]
+

Initialize authentication backend.

+
+ +
+
+airflow.providers.fab.auth_manager.api.auth.backend.basic_auth.auth_current_user()[source]
+

Authenticate and set current user if Authorization header exists.

+
+
+
+ +
+
+airflow.providers.fab.auth_manager.api.auth.backend.basic_auth.requires_authentication(function)[source]
+

Decorate functions that require authentication.

+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/auth/backend/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/auth/backend/index.html new file mode 100644 index 00000000000..f025ddf0f86 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/auth/backend/index.html @@ -0,0 +1,886 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.api.auth.backend — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/auth/backend/kerberos_auth/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/auth/backend/kerberos_auth/index.html new file mode 100644 index 00000000000..acad6610f21 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/auth/backend/kerberos_auth/index.html @@ -0,0 +1,955 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + +

find_user([username, email])

+
+
+

Attributes

+ ++++ + + + + + + + + + + + + + + +

log

CLIENT_AUTH

init_app

requires_authentication

+
+
+airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth.log[source]
+
+ +
+
+airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth.CLIENT_AUTH: tuple[str, str] | Any | None[source]
+
+ +
+
+airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth.find_user(username=None, email=None)[source]
+
+ +
+
+airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth.init_app[source]
+
+ +
+
+airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth.requires_authentication[source]
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/auth/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/auth/index.html new file mode 100644 index 00000000000..4887874d46f --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/auth/index.html @@ -0,0 +1,887 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.api.auth — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/index.html new file mode 100644 index 00000000000..06122831c61 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api/index.html @@ -0,0 +1,888 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.api — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api_endpoints/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api_endpoints/index.html new file mode 100644 index 00000000000..93f39d22ceb --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api_endpoints/index.html @@ -0,0 +1,882 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.api_endpoints — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api_endpoints/role_and_permission_endpoint/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api_endpoints/role_and_permission_endpoint/index.html new file mode 100644 index 00000000000..0b798404501 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api_endpoints/role_and_permission_endpoint/index.html @@ -0,0 +1,966 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + + + + + + + + + + + + + + + + +

get_role(*, role_name)

Get role.

get_roles(*[, order_by, offset])

Get roles.

get_permissions(*, limit[, offset])

Get permissions.

delete_role(*, role_name)

Delete a role.

patch_role(*, role_name[, update_mask])

Update a role.

post_role()

Create a new role.

+
+
+airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint.get_role(*, role_name)[source]
+

Get role.

+
+
+
+ +
+
+airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint.get_roles(*, order_by='name', limit, offset=None)[source]
+

Get roles.

+
+
+
+ +
+
+airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint.get_permissions(*, limit, offset=None)[source]
+

Get permissions.

+
+
+
+ +
+
+airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint.delete_role(*, role_name)[source]
+

Delete a role.

+
+
+
+ +
+
+airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint.patch_role(*, role_name, update_mask=None)[source]
+

Update a role.

+
+
+
+ +
+
+airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint.post_role()[source]
+

Create a new role.

+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api_endpoints/user_endpoint/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api_endpoints/user_endpoint/index.html new file mode 100644 index 00000000000..c5ba9482266 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/api_endpoints/user_endpoint/index.html @@ -0,0 +1,954 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.api_endpoints.user_endpoint — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.api_endpoints.user_endpoint

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + + + + + + + + + + + + + +

get_user(*, username)

Get a user.

get_users(*, limit[, order_by, offset])

Get users.

post_user()

Create a new user.

patch_user(*, username[, update_mask])

Update a user.

delete_user(*, username)

Delete a user.

+
+
+airflow.providers.fab.auth_manager.api_endpoints.user_endpoint.get_user(*, username)[source]
+

Get a user.

+
+
+
+ +
+
+airflow.providers.fab.auth_manager.api_endpoints.user_endpoint.get_users(*, limit, order_by='id', offset=None)[source]
+

Get users.

+
+
+
+ +
+
+airflow.providers.fab.auth_manager.api_endpoints.user_endpoint.post_user()[source]
+

Create a new user.

+
+
+
+ +
+
+airflow.providers.fab.auth_manager.api_endpoints.user_endpoint.patch_user(*, username, update_mask=None)[source]
+

Update a user.

+
+
+
+ +
+
+airflow.providers.fab.auth_manager.api_endpoints.user_endpoint.delete_user(*, username)[source]
+

Delete a user.

+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/definition/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/definition/index.html new file mode 100644 index 00000000000..14c7dcb1f48 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/definition/index.html @@ -0,0 +1,1030 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.cli_commands.definition — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.cli_commands.definition

+
+

Module Contents

+
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_USERNAME[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_USERNAME_OPTIONAL[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_FIRSTNAME[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_LASTNAME[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_ROLE[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_EMAIL[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_EMAIL_OPTIONAL[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_PASSWORD[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_USE_RANDOM_PASSWORD[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_USER_IMPORT[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_USER_EXPORT[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_CREATE_ROLE[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_LIST_ROLES[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_ROLES[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_PERMISSIONS[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_ROLE_RESOURCE[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_ROLE_ACTION[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_ROLE_ACTION_REQUIRED[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_ROLE_IMPORT[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_ROLE_EXPORT[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_ROLE_EXPORT_FMT[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ARG_INCLUDE_DAGS[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.USERS_COMMANDS = ()[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.ROLES_COMMANDS = ()[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.definition.SYNC_PERM_COMMAND[source]
+
+ +
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/index.html new file mode 100644 index 00000000000..a4287df60cc --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/index.html @@ -0,0 +1,885 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.cli_commands — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/role_command/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/role_command/index.html new file mode 100644 index 00000000000..14fd968a01b --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/role_command/index.html @@ -0,0 +1,966 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.cli_commands.role_command — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.cli_commands.role_command

+

Roles sub-commands.

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + +

roles_list(args)

List all existing roles.

roles_create(args)

Create new empty role in DB.

roles_delete(args)

Delete role in DB.

roles_add_perms(args)

Add permissions to role in DB.

roles_del_perms(args)

Delete permissions from role in DB.

roles_export(args)

Export all the roles from the database to a file including permissions.

roles_import(args)

Import all the roles into the db from the given json file including their permissions.

+
+
+airflow.providers.fab.auth_manager.cli_commands.role_command.roles_list(args)[source]
+

List all existing roles.

+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.role_command.roles_create(args)[source]
+

Create new empty role in DB.

+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.role_command.roles_delete(args)[source]
+

Delete role in DB.

+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.role_command.roles_add_perms(args)[source]
+

Add permissions to role in DB.

+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.role_command.roles_del_perms(args)[source]
+

Delete permissions from role in DB.

+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.role_command.roles_export(args)[source]
+

Export all the roles from the database to a file including permissions.

+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.role_command.roles_import(args)[source]
+

Import all the roles into the db from the given json file including their permissions.

+

Note, if a role already exists in the db, it is not overwritten, even when the permissions change.

+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/sync_perm_command/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/sync_perm_command/index.html new file mode 100644 index 00000000000..2fd0466f8ec --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/sync_perm_command/index.html @@ -0,0 +1,905 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.cli_commands.sync_perm_command — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.cli_commands.sync_perm_command

+

Sync permission command.

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + +

sync_perm(args)

Update permissions for existing roles and DAGs.

+
+
+airflow.providers.fab.auth_manager.cli_commands.sync_perm_command.sync_perm(args)[source]
+

Update permissions for existing roles and DAGs.

+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/user_command/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/user_command/index.html new file mode 100644 index 00000000000..46bc092f166 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/user_command/index.html @@ -0,0 +1,1058 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.cli_commands.user_command — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.cli_commands.user_command

+

User sub-commands.

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

UserSchema

user collection item schema.

+
+
+

Functions

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + +

users_list(args)

List users at the command line.

users_create(args)

Create new user in the DB.

user_reset_password(args)

Reset user password user from DB.

users_delete(args)

Delete user from DB.

users_manage_role(args[, remove])

Delete or appends user roles.

users_export(args)

Export all users to the json file.

users_import(args)

Import users from the json file.

+
+
+

Attributes

+ ++++ + + + + + + + + +

add_role

remove_role

+
+
+class airflow.providers.fab.auth_manager.cli_commands.user_command.UserSchema(*, only=None, exclude=(), many=False, context=None, load_only=(), dump_only=(), partial=None, unknown=None)[source]
+

Bases: marshmallow.Schema

+

user collection item schema.

+
+
+
+
+id[source]
+
+ +
+
+firstname[source]
+
+ +
+
+lastname[source]
+
+ +
+
+username[source]
+
+ +
+
+email[source]
+
+ +
+
+roles[source]
+
+ +
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.user_command.users_list(args)[source]
+

List users at the command line.

+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.user_command.users_create(args)[source]
+

Create new user in the DB.

+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.user_command.user_reset_password(args)[source]
+

Reset user password user from DB.

+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.user_command.users_delete(args)[source]
+

Delete user from DB.

+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.user_command.users_manage_role(args, remove=False)[source]
+

Delete or appends user roles.

+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.user_command.users_export(args)[source]
+

Export all users to the json file.

+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.user_command.users_import(args)[source]
+

Import users from the json file.

+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.user_command.add_role[source]
+
+ +
+
+airflow.providers.fab.auth_manager.cli_commands.user_command.remove_role[source]
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/utils/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/utils/index.html new file mode 100644 index 00000000000..69128c8bedd --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/cli_commands/utils/index.html @@ -0,0 +1,905 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.cli_commands.utils — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.cli_commands.utils

+
+

Module Contents

+
+

Functions

+ ++++ + + + + + +

get_application_builder()

+
+
+airflow.providers.fab.auth_manager.cli_commands.utils.get_application_builder()[source]
+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/decorators/auth/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/decorators/auth/index.html new file mode 100644 index 00000000000..28307b5db05 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/decorators/auth/index.html @@ -0,0 +1,892 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.decorators.auth — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.decorators.auth

+
+

Module Contents

+
+
+airflow.providers.fab.auth_manager.decorators.auth.T[source]
+
+ +
+
+airflow.providers.fab.auth_manager.decorators.auth.log[source]
+
+ +
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/decorators/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/decorators/index.html new file mode 100644 index 00000000000..a75e3bf5c80 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/decorators/index.html @@ -0,0 +1,881 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.decorators — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/fab_auth_manager/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/fab_auth_manager/index.html new file mode 100644 index 00000000000..565d6a6d826 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/fab_auth_manager/index.html @@ -0,0 +1,1185 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.fab_auth_manager — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.fab_auth_manager

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

FabAuthManager

Flask-AppBuilder auth manager.

+
+
+

Functions

+ ++++ + + + + + +

get_parser()

Generate documentation; used by Sphinx argparse.

+
+
+class airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager(appbuilder)[source]
+

Bases: airflow.auth.managers.base_auth_manager.BaseAuthManager

+

Flask-AppBuilder auth manager.

+

This auth manager is responsible for providing a backward compatible user management experience to users.

+
+
+
+
+static get_cli_commands()[source]
+

Vends CLI commands to be included in Airflow CLI.

+
+
+
+ +
+
+get_api_endpoints()[source]
+

Return API endpoint(s) definition for the auth manager.

+
+
+
+ +
+
+get_user_display_name()[source]
+

Return the user’s display name associated to the user in session.

+
+
+
+ +
+
+get_user()[source]
+

Return the user associated to the user in session.

+
+
+
+ +
+
+init()[source]
+

Run operations when Airflow is initializing.

+
+
+
+ +
+
+is_logged_in()[source]
+

Return whether the user is logged in.

+
+
+
+ +
+
+is_authorized_configuration(*, method, details=None, user=None)[source]
+

Return whether the user is authorized to perform a given action on configuration.

+
+
Parameters
+
    +
  • method (airflow.auth.managers.base_auth_manager.ResourceMethod) – the method to perform

  • +
  • details (airflow.auth.managers.models.resource_details.ConfigurationDetails | None) – optional details about the configuration

  • +
  • user (airflow.auth.managers.models.base_user.BaseUser | None) – the user to perform the action on. If not provided (or None), it uses the current user

  • +
+
+
+
+ +
+
+is_authorized_connection(*, method, details=None, user=None)[source]
+

Return whether the user is authorized to perform a given action on a connection.

+
+
Parameters
+
    +
  • method (airflow.auth.managers.base_auth_manager.ResourceMethod) – the method to perform

  • +
  • details (airflow.auth.managers.models.resource_details.ConnectionDetails | None) – optional details about the connection

  • +
  • user (airflow.auth.managers.models.base_user.BaseUser | None) – the user to perform the action on. If not provided (or None), it uses the current user

  • +
+
+
+
+ +
+
+is_authorized_dag(*, method, access_entity=None, details=None, user=None)[source]
+

Return whether the user is authorized to access the dag.

+

There are multiple scenarios:

+

1. dag_access is not provided which means the user wants to access the DAG itself and not a sub +entity (e.g. DAG runs). +2. dag_access is provided which means the user wants to access a sub entity of the DAG +(e.g. DAG runs).

+
+
    +
  1. If method is GET, then check the user has READ permissions on the DAG and the sub entity.

  2. +
  3. +
    Else, check the user has EDIT permissions on the DAG and method on the sub entity. However,

    if no specific DAG is targeted, just check the sub entity.

    +
    +
    +
  4. +
+
+
+
Parameters
+
    +
  • method (airflow.auth.managers.base_auth_manager.ResourceMethod) – The method to authorize.

  • +
  • access_entity (airflow.auth.managers.models.resource_details.DagAccessEntity | None) – The dag access entity.

  • +
  • details (airflow.auth.managers.models.resource_details.DagDetails | None) – The dag details.

  • +
  • user (airflow.auth.managers.models.base_user.BaseUser | None) – The user.

  • +
+
+
+
+ +
+
+is_authorized_dataset(*, method, details=None, user=None)[source]
+

Return whether the user is authorized to perform a given action on a dataset.

+
+
Parameters
+
    +
  • method (airflow.auth.managers.base_auth_manager.ResourceMethod) – the method to perform

  • +
  • details (airflow.auth.managers.models.resource_details.DatasetDetails | None) – optional details about the dataset

  • +
  • user (airflow.auth.managers.models.base_user.BaseUser | None) – the user to perform the action on. If not provided (or None), it uses the current user

  • +
+
+
+
+ +
+
+is_authorized_pool(*, method, details=None, user=None)[source]
+

Return whether the user is authorized to perform a given action on a pool.

+
+
Parameters
+
    +
  • method (airflow.auth.managers.base_auth_manager.ResourceMethod) – the method to perform

  • +
  • details (airflow.auth.managers.models.resource_details.PoolDetails | None) – optional details about the pool

  • +
  • user (airflow.auth.managers.models.base_user.BaseUser | None) – the user to perform the action on. If not provided (or None), it uses the current user

  • +
+
+
+
+ +
+
+is_authorized_variable(*, method, details=None, user=None)[source]
+

Return whether the user is authorized to perform a given action on a variable.

+
+
Parameters
+
    +
  • method (airflow.auth.managers.base_auth_manager.ResourceMethod) – the method to perform

  • +
  • details (airflow.auth.managers.models.resource_details.VariableDetails | None) – optional details about the variable

  • +
  • user (airflow.auth.managers.models.base_user.BaseUser | None) – the user to perform the action on. If not provided (or None), it uses the current user

  • +
+
+
+
+ +
+
+is_authorized_view(*, access_view, user=None)[source]
+

Return whether the user is authorized to access a read-only state of the installation.

+
+
Parameters
+
    +
  • access_view (airflow.auth.managers.models.resource_details.AccessView) – the specific read-only view/state the authorization request is about.

  • +
  • user (airflow.auth.managers.models.base_user.BaseUser | None) – the user to perform the action on. If not provided (or None), it uses the current user

  • +
+
+
+
+ +
+
+is_authorized_custom_view(*, method, resource_name, user=None)[source]
+

Return whether the user is authorized to perform a given action on a custom view.

+

A custom view can be a view defined as part of the auth manager. This view is then only available when +the auth manager is used as part of the environment. It can also be a view defined as part of a +plugin defined by a user.

+
+
Parameters
+
    +
  • method (airflow.auth.managers.base_auth_manager.ResourceMethod) – the method to perform

  • +
  • resource_name (str) – the name of the resource

  • +
  • user (airflow.auth.managers.models.base_user.BaseUser | None) – the user to perform the action on. If not provided (or None), it uses the current user

  • +
+
+
+
+ +
+
+get_permitted_dag_ids(*, methods=None, user=None, session=NEW_SESSION)[source]
+

Get readable or writable DAGs for user.

+

By default, reads all the DAGs and check individually if the user has permissions to access the DAG. +Can lead to some poor performance. It is recommended to override this method in the auth manager +implementation to provide a more efficient implementation.

+
+
Parameters
+
    +
  • methods (Container[airflow.auth.managers.base_auth_manager.ResourceMethod] | None) – whether filter readable or writable

  • +
  • user – the current user

  • +
  • session (sqlalchemy.orm.Session) – the session

  • +
+
+
+
+ +
+
+security_manager()[source]
+

Return the security manager specific to FAB.

+
+
+
+ +
+
+get_url_login(**kwargs)[source]
+

Return the login page url.

+
+
+
+ +
+
+get_url_logout()[source]
+

Return the logout page url.

+
+ +
+
+get_url_user_profile()[source]
+

Return the url to a page displaying info about the current user.

+
+
+
+ +
+ +
+
+airflow.providers.fab.auth_manager.fab_auth_manager.get_parser()[source]
+

Generate documentation; used by Sphinx argparse.

+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/index.html new file mode 100644 index 00000000000..36191dd2a8b --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/index.html @@ -0,0 +1,929 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager

+ + +
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/models/anonymous_user/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/models/anonymous_user/index.html new file mode 100644 index 00000000000..e8b2305b945 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/models/anonymous_user/index.html @@ -0,0 +1,919 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.models.anonymous_user — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.models.anonymous_user

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

AnonymousUser

User object used when no active user is logged in.

+
+
+class airflow.providers.fab.auth_manager.models.anonymous_user.AnonymousUser[source]
+

Bases: flask_login.AnonymousUserMixin, airflow.auth.managers.models.base_user.BaseUser

+

User object used when no active user is logged in.

+
+
+property roles[source]
+
+ +
+
+property perms[source]
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/models/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/models/index.html new file mode 100644 index 00000000000..ad9aa3269e0 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/models/index.html @@ -0,0 +1,1410 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.models — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.models

+ +
+

Package Contents

+
+

Classes

+ ++++ + + + + + + + + + + + + + + + + + + + + +

Action

Represents permission actions such as can_read.

Resource

Represents permission object such as User or Dag.

Role

Represents a user role to which permissions can be assigned.

Permission

Permission pair comprised of an Action + Resource combo.

User

Represents an Airflow user which has roles assigned to it.

RegisterUser

Represents a user registration.

+
+
+

Functions

+ ++++ + + + + + + + + +

add_index_on_ab_user_username_postgres(table, conn, **kw)

add_index_on_ab_register_user_username_postgres(table, ...)

+
+
+

Attributes

+ ++++ + + + + + + + + + + + +

Identity

assoc_permission_role

assoc_user_role

+
+
+airflow.providers.fab.auth_manager.models.Identity[source]
+
+ +
+
+class airflow.providers.fab.auth_manager.models.Action[source]
+

Bases: flask_appbuilder.models.sqla.Model

+

Represents permission actions such as can_read.

+
+
+__tablename__ = 'ab_permission'[source]
+
+ +
+
+id[source]
+
+ +
+
+name[source]
+
+ +
+
+__repr__()[source]
+

Return repr(self).

+
+ +
+ +
+
+class airflow.providers.fab.auth_manager.models.Resource[source]
+

Bases: flask_appbuilder.models.sqla.Model

+

Represents permission object such as User or Dag.

+
+
+__tablename__ = 'ab_view_menu'[source]
+
+ +
+
+id[source]
+
+ +
+
+name[source]
+
+ +
+
+__eq__(other)[source]
+

Return self==value.

+
+ +
+
+__neq__(other)[source]
+
+ +
+
+__repr__()[source]
+

Return repr(self).

+
+ +
+ +
+
+airflow.providers.fab.auth_manager.models.assoc_permission_role[source]
+
+ +
+
+class airflow.providers.fab.auth_manager.models.Role[source]
+

Bases: flask_appbuilder.models.sqla.Model

+

Represents a user role to which permissions can be assigned.

+
+
+__tablename__ = 'ab_role'[source]
+
+ +
+
+id[source]
+
+ +
+
+name[source]
+
+ +
+
+permissions[source]
+
+ +
+
+__repr__()[source]
+

Return repr(self).

+
+ +
+ +
+
+class airflow.providers.fab.auth_manager.models.Permission[source]
+

Bases: flask_appbuilder.models.sqla.Model

+

Permission pair comprised of an Action + Resource combo.

+
+
+__tablename__ = 'ab_permission_view'[source]
+
+ +
+
+__table_args__ = ()[source]
+
+ +
+
+id[source]
+
+ +
+
+action_id[source]
+
+ +
+
+action[source]
+
+ +
+
+resource_id[source]
+
+ +
+
+resource[source]
+
+ +
+
+__repr__()[source]
+

Return repr(self).

+
+ +
+ +
+
+airflow.providers.fab.auth_manager.models.assoc_user_role[source]
+
+ +
+
+class airflow.providers.fab.auth_manager.models.User[source]
+

Bases: flask_appbuilder.models.sqla.Model, airflow.auth.managers.models.base_user.BaseUser

+

Represents an Airflow user which has roles assigned to it.

+
+
+property created_by_fk[source]
+
+ +
+
+property changed_by_fk[source]
+
+ +
+
+property is_authenticated[source]
+
+ +
+
+property is_active[source]
+
+ +
+
+property is_anonymous[source]
+
+ +
+
+property perms[source]
+
+ +
+
+__tablename__ = 'ab_user'[source]
+
+ +
+
+id[source]
+
+ +
+
+first_name[source]
+
+ +
+
+last_name[source]
+
+ +
+
+username[source]
+
+ +
+
+password[source]
+
+ +
+
+active[source]
+
+ +
+
+email[source]
+
+ +
+
+last_login[source]
+
+ +
+
+login_count[source]
+
+ +
+
+fail_login_count[source]
+
+ +
+
+roles[source]
+
+ +
+
+created_on[source]
+
+ +
+
+changed_on[source]
+
+ +
+
+created_by[source]
+
+ +
+
+changed_by[source]
+
+ +
+
+classmethod get_user_id()[source]
+
+ +
+
+get_id()[source]
+
+ +
+
+get_name()[source]
+
+
+
+ +
+
+get_full_name()[source]
+
+ +
+
+__repr__()[source]
+

Return repr(self).

+
+ +
+ +
+
+class airflow.providers.fab.auth_manager.models.RegisterUser[source]
+

Bases: flask_appbuilder.models.sqla.Model

+

Represents a user registration.

+
+
+__tablename__ = 'ab_register_user'[source]
+
+ +
+
+id[source]
+
+ +
+
+first_name[source]
+
+ +
+
+last_name[source]
+
+ +
+
+username[source]
+
+ +
+
+password[source]
+
+ +
+
+email[source]
+
+ +
+
+registration_date[source]
+
+ +
+
+registration_hash[source]
+
+ +
+ +
+
+airflow.providers.fab.auth_manager.models.add_index_on_ab_user_username_postgres(table, conn, **kw)[source]
+
+ +
+
+airflow.providers.fab.auth_manager.models.add_index_on_ab_register_user_username_postgres(table, conn, **kw)[source]
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/openapi/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/openapi/index.html new file mode 100644 index 00000000000..6444993bea1 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/openapi/index.html @@ -0,0 +1,870 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.openapi — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/security_manager/constants/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/security_manager/constants/index.html new file mode 100644 index 00000000000..a45ec2af4ce --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/security_manager/constants/index.html @@ -0,0 +1,886 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.security_manager.constants — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.security_manager.constants

+
+

Module Contents

+
+
+airflow.providers.fab.auth_manager.security_manager.constants.EXISTING_ROLES[source]
+
+ +
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/security_manager/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/security_manager/index.html new file mode 100644 index 00000000000..950ba3a215b --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/security_manager/index.html @@ -0,0 +1,882 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.security_manager — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/security_manager/override/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/security_manager/override/index.html new file mode 100644 index 00000000000..c5e9e6a9ffc --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/security_manager/override/index.html @@ -0,0 +1,2395 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.security_manager.override — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.security_manager.override

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

FabAirflowSecurityManagerOverride

This security manager overrides the default AirflowSecurityManager security manager.

+
+
+

Attributes

+ ++++ + + + + + + + + +

log

MAX_NUM_DATABASE_USER_SESSIONS

+
+
+airflow.providers.fab.auth_manager.security_manager.override.log[source]
+
+ +
+
+airflow.providers.fab.auth_manager.security_manager.override.MAX_NUM_DATABASE_USER_SESSIONS = 50000[source]
+
+ +
+
+class airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride(appbuilder)[source]
+

Bases: airflow.www.security_manager.AirflowSecurityManagerV2

+

This security manager overrides the default AirflowSecurityManager security manager.

+

This security manager is used only if the auth manager FabAuthManager is used. It defines everything in +the security manager that is needed for the FabAuthManager to work. Any operation specific to +the AirflowSecurityManager should be defined here instead of AirflowSecurityManager.

+
+
Parameters
+

appbuilder – The appbuilder.

+
+
+
+
+property get_session[source]
+
+ +
+
+property auth_type[source]
+

Get the auth type.

+
+ +
+
+property is_auth_limited: bool[source]
+

Is the auth rate limited.

+
+
+
+ +
+
+property auth_rate_limit: str[source]
+

Get the auth rate limit.

+
+
+
+ +
+
+property auth_role_public[source]
+

Get the public role.

+
+ +
+
+property oauth_providers[source]
+

Oauth providers.

+
+ +
+
+property auth_ldap_tls_cacertdir[source]
+

LDAP TLS CA certificate directory.

+
+ +
+
+property auth_ldap_tls_cacertfile[source]
+

LDAP TLS CA certificate file.

+
+ +
+
+property auth_ldap_tls_certfile[source]
+

LDAP TLS certificate file.

+
+ +
+
+property auth_ldap_tls_keyfile[source]
+

LDAP TLS key file.

+
+ +
+
+property auth_ldap_allow_self_signed[source]
+

LDAP allow self signed.

+
+ +
+
+property auth_ldap_tls_demand[source]
+

LDAP TLS demand.

+
+ +
+
+property auth_ldap_server[source]
+

Get the LDAP server object.

+
+ +
+
+property auth_ldap_use_tls[source]
+

Should LDAP use TLS.

+
+ +
+
+property auth_ldap_bind_user[source]
+

LDAP bind user.

+
+ +
+
+property auth_ldap_bind_password[source]
+

LDAP bind password.

+
+ +
+ +

LDAP search object.

+
+ +
+
+property auth_ldap_search_filter[source]
+

LDAP search filter.

+
+ +
+
+property auth_ldap_uid_field[source]
+

LDAP UID field.

+
+ +
+
+property auth_ldap_firstname_field[source]
+

LDAP first name field.

+
+ +
+
+property auth_ldap_lastname_field[source]
+

LDAP last name field.

+
+ +
+
+property auth_ldap_email_field[source]
+

LDAP email field.

+
+ +
+
+property auth_ldap_append_domain[source]
+

LDAP append domain.

+
+ +
+
+property auth_ldap_username_format[source]
+

LDAP username format.

+
+ +
+
+property auth_ldap_group_field: str[source]
+

LDAP group field.

+
+
+
+ +
+
+property auth_roles_mapping: dict[str, list[str]][source]
+

The mapping of auth roles.

+
+
+
+ +
+
+property auth_user_registration_role_jmespath: str[source]
+

The JMESPATH role to use for user registration.

+
+
+
+ +
+
+property auth_remote_user_env_var: str[source]
+
+
+
+ +
+
+property api_login_allow_multiple_providers[source]
+
+ +
+
+property auth_username_ci[source]
+

Get the auth username for CI.

+
+ +
+
+property auth_ldap_bind_first[source]
+

LDAP bind first.

+
+ +
+
+property openid_providers[source]
+

Openid providers.

+
+ +
+
+property auth_type_provider_name[source]
+
+ +
+
+property auth_user_registration[source]
+

Will user self registration be allowed.

+
+ +
+
+property auth_user_registration_role[source]
+

The default user self registration role.

+
+ +
+
+property auth_roles_sync_at_login: bool[source]
+

Should roles be synced at login.

+
+
+
+ +
+
+property auth_role_admin[source]
+

Get the admin role.

+
+ +
+
+property oauth_whitelists[source]
+
+ +
+
+property builtin_roles[source]
+

Get the builtin roles.

+
+ +
+
+auth_view[source]
+

The obj instance for authentication view

+
+ +
+
+registeruser_view[source]
+

The obj instance for registering user view

+
+ +
+
+user_view[source]
+

The obj instance for user view

+
+ +
+
+user_model[source]
+
+ +
+
+role_model[source]
+
+ +
+
+action_model[source]
+
+ +
+
+resource_model[source]
+
+ +
+
+permission_model[source]
+

Views

+
+ +
+
+authdbview[source]
+

Override if you want your own Authentication DB view

+
+ +
+
+authldapview[source]
+

Override if you want your own Authentication LDAP view

+
+ +
+
+authoidview[source]
+

Override if you want your own Authentication OID view

+
+ +
+
+authoauthview[source]
+

Override if you want your own Authentication OAuth view

+
+ +
+
+authremoteuserview[source]
+

Override if you want your own Authentication REMOTE_USER view

+
+ +
+
+registeruserdbview[source]
+

Override if you want your own register user db view

+
+ +
+
+registeruseroidview[source]
+

Override if you want your own register user OpenID view

+
+ +
+
+registeruseroauthview[source]
+

Override if you want your own register user OAuth view

+
+ +
+
+actionmodelview[source]
+
+ +
+
+permissionmodelview[source]
+
+ +
+
+rolemodelview[source]
+
+ +
+
+registeruser_model[source]
+
+ +
+
+registerusermodelview[source]
+
+ +
+
+resourcemodelview[source]
+
+ +
+
+userdbmodelview[source]
+
+ +
+
+resetmypasswordview[source]
+
+ +
+
+resetpasswordview[source]
+
+ +
+
+userinfoeditview[source]
+
+ +
+
+userldapmodelview[source]
+
+ +
+
+useroauthmodelview[source]
+
+ +
+
+userremoteusermodelview[source]
+
+ +
+
+useroidmodelview[source]
+
+ +
+
+userstatschartview[source]
+
+ +
+
+jwt_manager[source]
+

Flask-JWT-Extended

+
+ +
+
+oid[source]
+

Flask-OpenID OpenID

+
+ +
+
+oauth[source]
+
+ +
+
+oauth_remotes: dict[str, Any][source]
+

Initialized (remote_app) providers dict {‘provider_name’, OBJ }

+
+ +
+
+oauth_user_info[source]
+
+ +
+
+oauth_allow_list: dict[str, list][source]
+

OAuth email allow list

+
+ +
+
+DAG_RESOURCES[source]
+
+ +
+
+VIEWER_PERMISSIONS = [(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (),...[source]
+
+ +
+
+USER_PERMISSIONS = [(), (), (), (), (), (), (), (), ()][source]
+
+ +
+
+OP_PERMISSIONS = [(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()][source]
+
+ +
+
+ADMIN_PERMISSIONS = [(), (), (), (), (), (), (), (), (), ()][source]
+
+ +
+
+ROLE_CONFIGS: list[dict[str, Any]][source]
+
+ +
+
+DAG_ACTIONS[source]
+
+ +
+
+register_views()[source]
+

Register FAB auth manager related views.

+
+ +
+
+create_login_manager()[source]
+

Create the login manager.

+
+
+
+ +
+
+create_jwt_manager()[source]
+

Create the JWT manager.

+
+ +
+
+reset_password(userid, password)[source]
+

Change/Reset a user’s password for auth db.

+

Password will be hashed and saved.

+
+
Parameters
+
    +
  • userid (int) – the user id to reset the password

  • +
  • password (str) – the clear text password to reset and save hashed on the db

  • +
+
+
+
+ +
+
+reset_user_sessions(user)[source]
+
+
+
+ +
+
+load_user_jwt(_jwt_header, jwt_data)[source]
+
+ +
+
+create_builtin_roles()[source]
+

Return FAB builtin roles.

+
+ +
+
+create_admin_standalone()[source]
+

Create an Admin user with a random password so that users can access airflow.

+
+
+
+ +
+
+create_db()[source]
+

Create the database.

+

Creates admin and public roles if they don’t exist.

+
+ +
+
+get_readable_dags(user)[source]
+

Get the DAGs readable by authenticated user.

+
+
+
+ +
+
+get_editable_dags(user)[source]
+

Get the DAGs editable by authenticated user.

+
+
+
+ +
+
+get_accessible_dags(user_actions, user, session=NEW_SESSION)[source]
+
+
+
+ +
+
+get_accessible_dag_ids(user, user_actions=None, session=NEW_SESSION)[source]
+
+
+
+ +
+
+static get_readable_dag_ids(user=None)[source]
+

Get the DAG IDs readable by authenticated user.

+
+
+
+ +
+
+static get_editable_dag_ids(user=None)[source]
+

Get the DAG IDs editable by authenticated user.

+
+
+
+ +
+
+can_access_some_dags(action, dag_id=None)[source]
+

Check if user has read or write access to some dags.

+
+
+
+ +
+
+get_all_permissions()[source]
+

Return all permissions as a set of tuples with the action and resource names.

+
+
+
+ +
+
+create_dag_specific_permissions()[source]
+

Add permissions to all DAGs.

+

Creates ‘can_read’, ‘can_edit’, and ‘can_delete’ permissions for all +DAGs, along with any access_control permissions provided in them.

+

This does iterate through ALL the DAGs, which can be slow. See sync_perm_for_dag +if you only need to sync a single DAG.

+
+
+
+ +
+
+prefixed_dag_id(dag_id)[source]
+

Return the permission name for a DAG id.

+
+
+
+ +
+
+is_dag_resource(resource_name)[source]
+

Determine if a resource belongs to a DAG or all DAGs.

+
+
+
+ +
+
+sync_perm_for_dag(dag_id, access_control=None)[source]
+

Sync permissions for given dag id.

+

The dag id surely exists in our dag bag as only / refresh button or DagBag will call this function.

+
+
Parameters
+
    +
  • dag_id (str) – the ID of the DAG whose permissions should be updated

  • +
  • access_control (dict[str, Collection[str]] | None) – a dict where each key is a role name and +each value is a set() of action names (e.g., +{‘can_read’}

  • +
+
+
Returns
+

+
+
Return type
+

None

+
+
+
+ +
+
+add_permissions_view(base_action_names, resource_name)[source]
+

Add an action on a resource to the backend.

+
+
Parameters
+
    +
  • base_action_names

    +
    list of permissions from view (all exposed methods):

    ’can_add’,’can_edit’ etc…

    +
    +
    +

  • +
  • resource_name – name of the resource to add

  • +
+
+
+
+ +
+
+add_permissions_menu(resource_name)[source]
+

Add menu_access to resource on permission_resource.

+
+
Parameters
+

resource_name – The resource name

+
+
+
+ +
+
+security_cleanup(baseviews, menus)[source]
+

Cleanup all unused permissions from the database.

+
+
Parameters
+
    +
  • baseviews – A list of BaseViews class

  • +
  • menus – Menu class

  • +
+
+
+
+ +
+
+sync_roles()[source]
+

Initialize default and custom roles with related permissions.

+
    +
  1. Init the default role(Admin, Viewer, User, Op, public) +with related permissions.

  2. +
  3. Init the custom role(dag-user) with related permissions.

  4. +
+
+
+
+ +
+
+create_perm_vm_for_all_dag()[source]
+

Create perm-vm if not exist and insert into FAB security model for all-dags.

+
+
+
+ +
+
+add_homepage_access_to_custom_roles()[source]
+

Add Website.can_read access to all custom roles.

+
+
+
+ +
+
+update_admin_permission()[source]
+

Add missing permissions to the table for admin.

+

Admin should get all the permissions, except the dag permissions +because Admin already has Dags permission. +Add the missing ones to the table for admin.

+
+
+
+ +
+
+clean_perms()[source]
+

FAB leaves faulty permissions that need to be cleaned up.

+
+
+
+ +
+
+permission_exists_in_one_or_more_roles(resource_name, action_name, role_ids)[source]
+

Efficiently check if a certain permission exists on a list of role ids; used by has_access.

+
+
Parameters
+
    +
  • resource_name (str) – The view’s name to check if exists on one of the roles

  • +
  • action_name (str) – The permission name to check if exists

  • +
  • role_ids (list[int]) – a list of Role ids

  • +
+
+
Returns
+

Boolean

+
+
Return type
+

bool

+
+
+
+ +
+
+perms_include_action(perms, action_name)[source]
+
+ +
+
+init_role(role_name, perms)[source]
+

Initialize the role with actions and related resources.

+
+
Parameters
+
    +
  • role_name

  • +
  • perms

  • +
+
+
+
+ +
+
+bulk_sync_roles(roles)[source]
+

Sync the provided roles and permissions.

+
+
+
+ +
+
+sync_resource_permissions(perms=None)[source]
+

Populate resource-based permissions.

+
+
+
+ +
+
+update_role(role_id, name)[source]
+

Update a role in the database.

+
+
+
+ +
+
+add_role(name)[source]
+

Add a role in the database.

+
+
+
+ +
+
+find_role(name)[source]
+

Find a role in the database.

+
+
Parameters
+

name – the role name

+
+
+
+ +
+
+get_all_roles()[source]
+
+ +
+
+delete_role(role_name)[source]
+

Delete the given Role.

+
+
Parameters
+

role_name (str) – the name of a role in the ab_role table

+
+
+
+ +
+
+get_roles_from_keys(role_keys)[source]
+

Construct a list of FAB role objects, from a list of keys.

+

NOTE: +- keys are things like: “LDAP group DNs” or “OAUTH group names” +- we use AUTH_ROLES_MAPPING to map from keys, to FAB role names

+
+
Parameters
+

role_keys (list[str]) – the list of FAB role keys

+
+
+
+ +
+
+get_public_role()[source]
+
+ +
+
+add_user(username, first_name, last_name, email, role, password='', hashed_password='')[source]
+

Create a user.

+
+ +
+
+load_user(user_id)[source]
+
+ +
+
+get_user_by_id(pk)[source]
+
+ +
+
+count_users()[source]
+

Return the number of users in the database.

+
+ +
+
+add_register_user(username, first_name, last_name, email, password='', hashed_password='')[source]
+

Add a registration request for the user.

+

:rtype : RegisterUser

+
+ +
+
+find_user(username=None, email=None)[source]
+

Find user by username or email.

+
+ +
+
+find_register_user(registration_hash)[source]
+
+ +
+
+update_user(user)[source]
+
+
+
+ +
+
+del_register_user(register_user)[source]
+

Delete registration object from database.

+
+
Parameters
+

register_user – RegisterUser object to delete

+
+
+
+ +
+
+get_all_users()[source]
+
+ +
+
+update_user_auth_stat(user, success=True)[source]
+

Update user authentication stats.

+

This is done upon successful/unsuccessful authentication attempts.

+
+
Parameters
+
    +
  • user – The identified (but possibly not successfully authenticated) user +model

  • +
  • success – Defaults to true, if true increments login_count, updates +last_login, and resets fail_login_count to 0, if false increments +fail_login_count on user model.

  • +
+
+
+
+ +
+
+get_action(name)[source]
+

Get an existing action record.

+
+
Parameters
+

name (str) – name

+
+
+
+ +
+
+create_action(name)[source]
+

Add an action to the backend, model action.

+
+
Parameters
+

name – name of the action: ‘can_add’,’can_edit’ etc…

+
+
+
+ +
+
+delete_action(name)[source]
+

Delete a permission action.

+
+
Parameters
+

name (str) – Name of action to delete (e.g. can_read).

+
+
+
+ +
+
+get_resource(name)[source]
+

Return a resource record by name, if it exists.

+
+
Parameters
+

name (str) – Name of resource

+
+
+
+ +
+
+create_resource(name)[source]
+

Create a resource with the given name.

+
+
Parameters
+

name – The name of the resource to create created.

+
+
+
+ +
+
+get_all_resources()[source]
+

Get all existing resource records.

+
+
+
+ +
+
+delete_resource(name)[source]
+

Delete a Resource from the backend.

+
+
Parameters
+

name (str) – name of the resource

+
+
+
+ +
+
+get_permission(action_name, resource_name)[source]
+

Get a permission made with the given action->resource pair, if the permission already exists.

+
+
Parameters
+
    +
  • action_name (str) – Name of action

  • +
  • resource_name (str) – Name of resource

  • +
+
+
+
+ +
+
+get_resource_permissions(resource)[source]
+

Retrieve permission pairs associated with a specific resource object.

+
+
Parameters
+

resource (airflow.providers.fab.auth_manager.models.Resource) – Object representing a single resource.

+
+
+
+ +
+
+create_permission(action_name, resource_name)[source]
+

Add a permission on a resource to the backend.

+
+
Parameters
+
    +
  • action_name – name of the action to add: ‘can_add’,’can_edit’ etc…

  • +
  • resource_name – name of the resource to add

  • +
+
+
+
+ +
+
+delete_permission(action_name, resource_name)[source]
+

Delete the permission linking an action->resource pair.

+

Doesn’t delete the underlying action or resource.

+
+
Parameters
+
    +
  • action_name (str) – Name of existing action

  • +
  • resource_name (str) – Name of existing resource

  • +
+
+
+
+ +
+
+add_permission_to_role(role, permission)[source]
+

Add an existing permission pair to a role.

+
+
Parameters
+
+
+
+
+ +
+
+remove_permission_from_role(role, permission)[source]
+

Remove a permission pair from a role.

+
+
Parameters
+
+
+
+
+ +
+
+get_oid_identity_url(provider_name)[source]
+

Return the OIDC identity provider URL.

+
+
+
+ +
+
+static get_user_roles(user=None)[source]
+

Get all the roles associated with the user.

+
+
Parameters
+

user – the ab_user in FAB model.

+
+
Returns
+

a list of roles associated with the user.

+
+
+
+ +
+
+auth_user_ldap(username, password)[source]
+

Authenticate user with LDAP.

+

NOTE: this depends on python-ldap module.

+
+
Parameters
+
    +
  • username – the username

  • +
  • password – the password

  • +
+
+
+
+ +
+
+auth_user_db(username, password)[source]
+

Authenticate user, auth db style.

+
+
Parameters
+
    +
  • username – The username or registered email address

  • +
  • password – The password, will be tested against hashed password on db

  • +
+
+
+
+ +
+
+oauth_user_info_getter(func)[source]
+

Get OAuth user info for all the providers.

+

Receives provider and response return a dict with the information returned from the provider. +The returned user info dict should have its keys with the same name as the User Model.

+

Use it like this an example for GitHub

+
@appbuilder.sm.oauth_user_info_getter
+def my_oauth_user_info(sm, provider, response=None):
+    if provider == "github":
+        me = sm.oauth_remotes[provider].get("user")
+        return {"username": me.data.get("login")}
+    return {}
+
+
+
+
+
+ +
+
+get_oauth_user_info(provider, resp)[source]
+

There are different OAuth APIs with different ways to retrieve user info.

+

All providers have different ways to retrieve user info.

+
+
+
+ +
+
+static oauth_token_getter()[source]
+

Get authentication (OAuth) token.

+
+ +
+
+check_authorization(perms=None, dag_id=None)[source]
+

Check the logged-in user has the specified permissions.

+
+
+
+ +
+
+set_oauth_session(provider, oauth_response)[source]
+

Set the current session with OAuth user secrets.

+
+ +
+
+get_oauth_token_key_name(provider)[source]
+

Return the token_key name for the oauth provider.

+

If none is configured defaults to oauth_token +this is configured using OAUTH_PROVIDERS and token_key key.

+
+ +
+
+get_oauth_token_secret_name(provider)[source]
+

Get the token_secret name for the oauth provider.

+

If none is configured, defaults to oauth_secret. This is configured +using OAUTH_PROVIDERS and token_secret.

+
+ +
+
+auth_user_oauth(userinfo)[source]
+

Authenticate user with OAuth.

+
+
Userinfo
+

dict with user information +(keys are the same as User model columns)

+
+
+
+ +
+
+auth_user_oid(email)[source]
+

Openid user Authentication.

+
+
Parameters
+

email – user’s email to authenticate

+
+
+
+ +
+
+auth_user_remote_user(username)[source]
+

REMOTE_USER user Authentication.

+
+
Parameters
+

username – user’s username for remote auth

+
+
+
+ +
+
+get_user_menu_access(menu_names=None)[source]
+
+
+
+ +
+
+static ldap_extract_list(ldap_dict, field_name)[source]
+
+
+
+ +
+
+static ldap_extract(ldap_dict, field_name, fallback)[source]
+
+
+
+ +
+
+filter_roles_by_perm_with_action(action_name, role_ids)[source]
+

Find roles with permission.

+
+
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/index.html new file mode 100644 index 00000000000..e51441ac7af --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/index.html @@ -0,0 +1,885 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.views — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/permissions/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/permissions/index.html new file mode 100644 index 00000000000..3d3432dc44e --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/permissions/index.html @@ -0,0 +1,1101 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.views.permissions — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.views.permissions

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + + + + +

ActionModelView

Customize permission names for FAB's builtin PermissionModelView.

PermissionPairModelView

Customize permission names for FAB's builtin PermissionViewModelView.

ResourceModelView

Customize permission names for FAB's builtin ViewMenuModelView.

+
+
+class airflow.providers.fab.auth_manager.views.permissions.ActionModelView(**kwargs)[source]
+

Bases: flask_appbuilder.security.views.PermissionModelView

+

Customize permission names for FAB’s builtin PermissionModelView.

+
+
+class_permission_name[source]
+
+ +
+
+route_base = '/actions'[source]
+
+ +
+
+method_permission_name[source]
+
+ +
+
+base_permissions[source]
+
+ +
+
+list_title[source]
+
+ +
+
+show_title[source]
+
+ +
+
+add_title[source]
+
+ +
+
+edit_title[source]
+
+ +
+
+label_columns[source]
+
+ +
+ +
+
+class airflow.providers.fab.auth_manager.views.permissions.PermissionPairModelView(**kwargs)[source]
+

Bases: flask_appbuilder.security.views.PermissionViewModelView

+

Customize permission names for FAB’s builtin PermissionViewModelView.

+
+
+class_permission_name[source]
+
+ +
+
+route_base = '/permissions'[source]
+
+ +
+
+method_permission_name[source]
+
+ +
+
+base_permissions[source]
+
+ +
+
+list_title[source]
+
+ +
+
+show_title[source]
+
+ +
+
+add_title[source]
+
+ +
+
+edit_title[source]
+
+ +
+
+label_columns[source]
+
+ +
+
+list_columns = ['action', 'resource'][source]
+
+ +
+ +
+
+class airflow.providers.fab.auth_manager.views.permissions.ResourceModelView(**kwargs)[source]
+

Bases: flask_appbuilder.security.views.ViewMenuModelView

+

Customize permission names for FAB’s builtin ViewMenuModelView.

+
+
+class_permission_name[source]
+
+ +
+
+route_base = '/resources'[source]
+
+ +
+
+method_permission_name[source]
+
+ +
+
+base_permissions[source]
+
+ +
+
+list_title[source]
+
+ +
+
+show_title[source]
+
+ +
+
+add_title[source]
+
+ +
+
+edit_title[source]
+
+ +
+
+label_columns[source]
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/roles_list/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/roles_list/index.html new file mode 100644 index 00000000000..2af79fa27c7 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/roles_list/index.html @@ -0,0 +1,925 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.views.roles_list — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.views.roles_list

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

CustomRoleModelView

Customize permission names for FAB's builtin RoleModelView.

+
+
+class airflow.providers.fab.auth_manager.views.roles_list.CustomRoleModelView(**kwargs)[source]
+

Bases: flask_appbuilder.security.views.RoleModelView

+

Customize permission names for FAB’s builtin RoleModelView.

+
+
+class_permission_name[source]
+
+ +
+
+method_permission_name[source]
+
+ +
+
+base_permissions[source]
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/user/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/user/index.html new file mode 100644 index 00000000000..438c3d3b7c7 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/user/index.html @@ -0,0 +1,1052 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.views.user — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.views.user

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + + + + + + + + + + + + + +

MultiResourceUserMixin

Remaps UserModelView permissions to new resources and actions.

CustomUserLDAPModelView

Customize permission names for FAB's builtin UserLDAPModelView.

CustomUserOAuthModelView

Customize permission names for FAB's builtin UserOAuthModelView.

CustomUserOIDModelView

Customize permission names for FAB's builtin UserOIDModelView.

CustomUserRemoteUserModelView

Customize permission names for FAB's builtin UserRemoteUserModelView.

CustomUserDBModelView

Customize permission names for FAB's builtin UserDBModelView.

+
+
+class airflow.providers.fab.auth_manager.views.user.MultiResourceUserMixin[source]
+

Remaps UserModelView permissions to new resources and actions.

+
+
+property class_permission_name[source]
+

Returns appropriate permission name depending on request method name.

+
+ +
+
+class_permission_name_mapping[source]
+
+ +
+
+method_permission_name[source]
+
+ +
+
+base_permissions[source]
+
+ +
+
+show(pk)[source]
+
+ +
+ +
+
+class airflow.providers.fab.auth_manager.views.user.CustomUserLDAPModelView(**kwargs)[source]
+

Bases: MultiResourceUserMixin, flask_appbuilder.security.views.UserLDAPModelView

+

Customize permission names for FAB’s builtin UserLDAPModelView.

+
+
+class_permission_name_mapping[source]
+
+ +
+
+method_permission_name[source]
+
+ +
+
+base_permissions[source]
+
+ +
+ +
+
+class airflow.providers.fab.auth_manager.views.user.CustomUserOAuthModelView(**kwargs)[source]
+

Bases: MultiResourceUserMixin, flask_appbuilder.security.views.UserOAuthModelView

+

Customize permission names for FAB’s builtin UserOAuthModelView.

+
+ +
+
+class airflow.providers.fab.auth_manager.views.user.CustomUserOIDModelView(**kwargs)[source]
+

Bases: MultiResourceUserMixin, flask_appbuilder.security.views.UserOIDModelView

+

Customize permission names for FAB’s builtin UserOIDModelView.

+
+ +
+
+class airflow.providers.fab.auth_manager.views.user.CustomUserRemoteUserModelView(**kwargs)[source]
+

Bases: MultiResourceUserMixin, flask_appbuilder.security.views.UserRemoteUserModelView

+

Customize permission names for FAB’s builtin UserRemoteUserModelView.

+
+
+class_permission_name_mapping[source]
+
+ +
+
+method_permission_name[source]
+
+ +
+
+base_permissions[source]
+
+ +
+ +
+
+class airflow.providers.fab.auth_manager.views.user.CustomUserDBModelView(**kwargs)[source]
+

Bases: MultiResourceUserMixin, flask_appbuilder.security.views.UserDBModelView

+

Customize permission names for FAB’s builtin UserDBModelView.

+
+
+class_permission_name_mapping[source]
+
+ +
+
+method_permission_name[source]
+
+ +
+
+base_permissions[source]
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/user_edit/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/user_edit/index.html new file mode 100644 index 00000000000..d68efe267b6 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/user_edit/index.html @@ -0,0 +1,993 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.views.user_edit — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.views.user_edit

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + + + + + + + +

CustomUserInfoEditView

Customize permission names for FAB's builtin UserInfoEditView.

CustomResetMyPasswordView

Customize permission names for FAB's builtin ResetMyPasswordView.

CustomResetPasswordView

Customize permission names for FAB's builtin ResetPasswordView.

+
+
+class airflow.providers.fab.auth_manager.views.user_edit.CustomUserInfoEditView[source]
+

Bases: flask_appbuilder.security.views.UserInfoEditView

+

Customize permission names for FAB’s builtin UserInfoEditView.

+
+
+class_permission_name[source]
+
+ +
+
+route_base = '/userinfoeditview'[source]
+
+ +
+
+method_permission_name[source]
+
+ +
+
+base_permissions[source]
+
+ +
+ +
+
+class airflow.providers.fab.auth_manager.views.user_edit.CustomResetMyPasswordView[source]
+

Bases: flask_appbuilder.security.views.ResetMyPasswordView

+

Customize permission names for FAB’s builtin ResetMyPasswordView.

+
+
+class_permission_name[source]
+
+ +
+
+method_permission_name[source]
+
+ +
+
+base_permissions[source]
+
+ +
+ +
+
+class airflow.providers.fab.auth_manager.views.user_edit.CustomResetPasswordView[source]
+

Bases: flask_appbuilder.security.views.ResetPasswordView

+

Customize permission names for FAB’s builtin ResetPasswordView.

+
+
+class_permission_name[source]
+
+ +
+
+method_permission_name[source]
+
+ +
+
+base_permissions[source]
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/user_stats/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/user_stats/index.html new file mode 100644 index 00000000000..2e8755f52cf --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/auth_manager/views/user_stats/index.html @@ -0,0 +1,931 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.views.user_stats — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab.auth_manager.views.user_stats

+
+

Module Contents

+
+

Classes

+ ++++ + + + + + +

CustomUserStatsChartView

Customize permission names for FAB's builtin UserStatsChartView.

+
+
+class airflow.providers.fab.auth_manager.views.user_stats.CustomUserStatsChartView(**kwargs)[source]
+

Bases: flask_appbuilder.security.views.UserStatsChartView

+

Customize permission names for FAB’s builtin UserStatsChartView.

+
+
+class_permission_name[source]
+
+ +
+
+route_base = '/userstatschartview'[source]
+
+ +
+
+method_permission_name[source]
+
+ +
+
+base_permissions[source]
+
+ +
+ +
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/index.html new file mode 100644 index 00000000000..71fe6ae2fcc --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_api/airflow/providers/fab/index.html @@ -0,0 +1,931 @@ + + + + + + + + + + + + airflow.providers.fab — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

airflow.providers.fab

+
+

Subpackages

+ +
+
+

Package Contents

+
+
+airflow.providers.fab.__version__ = '1.0.4'[source]
+
+ +
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_images/add-role.png b/docs-archive/apache-airflow-providers-fab/1.0.4/_images/add-role.png new file mode 100644 index 0000000000000000000000000000000000000000..2268811297095f79bfde33bb1f9e18334be42aaa GIT binary patch literal 30509 zcma&N2Uru`*Do3b1*9sXAWA?GR760e3y~%Q0wPUmK@d>s(rZ9aq=|@#N{RGN=pCXU zpd!6V4ZVaCNi?1(YL5$K6?TSpNL=0((0Q#SOWS#9ohZsvo*Zc#yG^=X(Hu1zq?+5^v{ zv;LgF&C?0$XjHu(MY)GTgsC~^2{ettfG z;!Q25hJXu7=Y)%)xA(ObemSip-ewm;Km0HiStyg#hWz}qx}l>(JG8dc{QPHsigig_ zPNYjlMuR2bXw^<-|C(R&;qz_^wkn7R&IE(8cd@PdBO>L160*P!0Rf$Z3;9m)6gPh}|6z+fsCCc{RN(eZvp7 zbTHT}p$fFtL0zGR!G_>4SP8VK!6c9c zYC!(aBL)yn1T4DmD!r$F5Al_`0sd4FLP5)J1<*jP%uxUKqKCl>5&t}ftw8g80KGY+ z5=_F5li)G8O;%Hm#*f|Mcm+QC`04M(ov7OJL~Og5({KPg=fAQ&Xr5?lEVnrLYBFcx z+E1S__3miDx)sjAz`*-lsf)GcEUc`*V&CfKl+#N~NofXU-p?aHILmWZUO^$0?`>Rm zQBkKw>u%tF0)H603Io3(NZBRCz-5Li=Q|QLADu&Z{Z3h1UmJTT^XYEedD*AUK0n!* zyUIl^%Jw#AH3VeoKVJ8Jr?CI^Yw%(3u(wF=d@%hblS<@xZ!iB*SK^O2Fq_)a(xRD% zea5uV*;>tzkN7*%e*FMqu+MsaZ~T)as)U?TWKk}}aOB^Y{sYLPi@C=#04hKsT+lh%Wnf|udRKYB03603<67vo39{#w zy-%8;$_r?4G=lVdGa&Qtof{1z`zDnEk1F6u9(tq}=||S@9b;-sh49&i#ln zFY}4xinPSuMlDTd>!iF`Y;FW{$&@D4!tbXyO_#zHyd6#KwYd((%dSESe__^(6i215 z)cVf8QVa21A*~F*^e`5od>$-#o`?9*=kz+xYesDlj=nzrBapK5>hyy5+IX6t?JnYd z!iPBwRZ&sV`Shc)=;i*t<@bLD!=4Xba-H9@P1zJ0W1JWk+1yM!*zC+lxwyFSh6`p< zKaMRuY)>((_6Uppy!~D3uEmx<>R`e`WPzrjpy1_S688X(iwrLwO4=Vd{O(RwAN94c zNP(%lySqOTJr^Qh@(j0oq8|Iab&HFHtFzU<#G|LGN?XAbF2JFej*s_*QH!l!zP{CnoX86}N0CqQzgP18Tx8iq$hPRq#D z3lT`33sR9n4x_BVAeu-W9+@YE_MPCKV-J1GjZg~qvc5Alkjo0Rn8vep-)_A&vCx@f zdu9r)=$o#^z-AN7O4n=-_W---Tcarht55!SlJPdX>lR%~ z)h=UKj?Xm@Q;W{j(o_t#{eB`ZKPoT?uPS=U<$$;TQ|YjH={@m^hzN(ere2%oX#`=j(61c^XXp zxqUOjnv|bl40NX|t;y@5l`iTJ3=BlSAltkMp^q5f4t8ReI7)BcVjsdq8lG=q@4aDl zC#Qcwf)NtWJ6PB~0IukltA2VtYNE03X@>fN-s3L_>!FME^lax!@EC!YmQ6nV`g{^k zLh!K<+ox6OJyl`vbTAPL9^otBm15zDlcB(PhVzXE>S7o|QJuUCM|H{f`prrOKYr%H$YP;l5ekyLN{zlM;wa zy!1iTB7G2Nx%(@jlM8#6)|k9TjchMJM8aWZxF^|r)+6w44L zE8;kKZP83iTkAsk%u)+lDe%fG!z;Fu2Vp1aA04$2?iq*x;|);3zigf7Ub-)qrKn?& zW6`(yoz1b%A}J3^)#wwvNPX ztGcdW*7<75WLo;2j@PPx1)57;8OB7h4Gn)uP4u!J7*`j*@W4ZO75>sC5Xbfcra)t8 zs+Y015cY>9`n}SKk!y;_B{|YC_inZ0KVW>B5NPa>?X zRnk@{3KvlqyOP}m9xckV9)FSA{l>m zkd1xCE@N-j#y<7_C~g|eds8DZv#5_I@}>>54(ewK0G2- z^n8CNo=GSP@m)E#cvTIEii#AJ`M6dSSCuQScFwyX-lwk0dCfGbKsb~7>F(`QBgyzsyLW_Hjw%uH zO~+d0!qMOseR^0wf5XN1%qs_Q1@AA@(&y-14^C81TR!Fq_7C+>@DKa8Zu-M*?$)Wx zW4&5q#SviNjoQNNNuNRt>#tG*=-Bs^1Au0+NHqj3mlL9hb04B>}65PrCI zh(h|{FxXoNnD7Bv(EI=6@&DE{*z*6i>;Kl~7Fio2{gx^UgKc!bg9vZ%{QvI+;iLaM zrMiR;5Y>`@r3>ozp+udSN@Qv!!W2S*(?{6CqXz3@K; z_w`U#TQ||&i*Dx-H*cyzcyO6b+`N4$_E4_TX72>`g?0K{t>bJ*@N|cAe^pP2o%N|T zca~0C^P*&x(*`$XBEC+YQa|DOW&-saNWY}QVEb@g?{G=1zKDP~biC^=7}E0d>xz@I zedTDN@q)kk`uRnsU+O4hZ=QDbS+0Oh)d+w65rCcjwCHPOlo1njxXAj#VfThfKl>WIN1s(bYtK0t4LWcQ z80|)nZqh7^LFyVzM1kvTNyC_?Qt#6ZZi2o%C`7vmBxlzbw402H{3Tqs!#~-0_55bH z6SriZ&Jve&pSc=VyWaa@T|ci*v7aNxUS?<8K`jsHWT>bkO zr^wyz*&UtjL{Re2&{fG3>?(JFUX#9&k%%kz^QcgaZFFB`y|Ao9XW8HrB61^QV{5(x z0++K&elBTXG#=oSREl@P6ZRiz2?37hJ?Dd_(Yg3c>g9`a?WA3y66aB*jsWxX}O)(AV)WF zZzE0A+}PO8Tjioo@OcHVKN;fMT1DZVhN>jAg17UN(!#>4gt@UQr&)cr@gsi3m=+Uc z;7i~M?8_q#azb{tP&{8Lf#G1QL(IoG&9>)t*|n~>hQ}M}+c`G;SQI0x!f6e&qB>YrnO&=lb7;NW0n#Hq+b zdkTZZR^^-(w+fz!zzhrz+mvxTqgCNG(#b4xif%z)9lAO@TQ!(%x!&H1F+?SQvZwVK zJ=eG#!oZ(NMF(wd&bG&96d=M&HmmAAmQUXHL^k+1UkIgsEV(2=Ave4#SNHX`;iKRa zL{7{i_s>gu*X^%>;r^gZVCPSp+YBde;c-1ZR_ETFSGXN}u$+Tl)n#Qpr|37J?bEHa zw^T~C8ZNeIJ( z!_y!&euifB%DSYQno=jv@NC!ZsdDu{dgBkkC8_(s{@tDRiH>~#tA9-+OZ&8jA*w-N zD>4cJt{M=SZTkA~E7g7@VXv5ZA6Fms_4N@=Nca#07@^Flvuu;->%LnFA|{2K_O`a^ zN1MyDy3qtFwm*}X#Kd@{Js7luwn-+wzO_$61bbkA>UwMX5C>)r9Cx84DGwo^pab*x zP(F)`!auBWO>;?iM5q~~qD6hAcyIdjC?IryhyznG0xw>cZms^vA=|iq6^RXU^UrN; zRE)s8n4PM5MbE}dhx_Q^L3uuX=cxV27C~X(n=72d5d7{y9E6ug#;~U+@{!uT$i(Fu zJk|xLw9YoM(DkV$H75`O%pE6ZMsSS3bA+wpu(5rF^UYt2-DExSbBO?@G}we|P~8X& zg6~^U6UEN*hs6%y*h=_a4ccll?$?J)YFW6yEE%<4qQ(|e*Q3q6g2q(K?Ypb|dybX( z_n0^}TiMGgXyj5Indy>FC&{?zejv{pamuTQ@X7yZJK1# z&*o8u^-^!BF!YuW!fOLfKYup&w8T1FFq7IZz}BhopuKNi8^|V)pH3=#=W<0z-9PRS zmY#@-i7=V^>v|clR5>Lia83$_^@wQH=o=W!mS$)a6y%e4_Q%hgy#{A;){)p}mY@qA ztTUJ%%grAaI)E5>_w!(XTOY<(@d^+~PIcJ5AuWCXHAm+P+yofWm^AW{Clj1#GB0=z zqI$k4=iNgcQ&10X>B`YfnGv+GR^;_QVFGXzoxo$Bpe-TijykZ;j^Ujj-D#}%uD_3Z zzu2|hpM92oSJ2(A`?wJ*j8cAchBTq-TPt_7B4GdeZjTH0+mFsz1a*m3YMij@VSmh@ zAUAGE*-no+M-Ol^C}}k5=4dCOrDV62^1pg9mAm^SZc@*Ip2Q z5FYw9Ii^HjXfJQKOu3@6l0Q8nK0!41Vij4~RA3ODmJi7^eh_!fx>?bKy!2CXb7kaD zPq4MyAo%-Jf0w@>+W*JSr_zpg#mDH!Iy#jKDX=vTZ`ItBv39n0T>NT%Z^_}|{a-G$ zbxM}uI;$e?k)V=Ly`0y(Vk*Oh$dq{c@+0HC>jMRdy1q5tIr0q`CKWd>vzH%kIg<1$ zZs%i9s1Q$PQop39k4JrsO`|@@vhB#$5nr8ddG*}S`4p*Ib7;?i_uR87N#=a8@RQ^P zUAB+nK@BHV1lgeS#maRWzM7p&k4M?<%f!f(=^kdGWmb~LaAkEnrKpXcRXOtkFmkK8 zzr9jKLtQ_8u zOVU#9($TAgyl94gs0F3re0`+bN5c(tXjvGh+Uha%;4)n%lZ+aGTp9h@^wvOUQi zWc~X3HA>MS+*a0wGlQj#Cf>T#u}CrOr9aD^I5NfC(7>Q&zGd(9#^-Cx%gZ~lPY`yG zAN!y*?gY60w7f~bfcLFGn?-G8gPiz@GOznUoFC$22WqqV<(@$gX>SOnmg%>m0NjGQuFF-G^o*qrR|Hkd9xP=uUeAN_ z9FqNA#3QyFHcN_D$(PuFZ|aHv{H4G%<9_l!>UPPgQ>W-KF`^ugS7iA1@$lt0A6?@e z_~_iWclh*FpKuG2AM+XoOLMWg-Qs%|6G=J)0WJxF7&-Y+e5_{Ox-KQD>yOssKdZ(h z@A$Vf7aGmk&8i)5C&x~#MmB3ILt}?4dwF@Kmyc-Qi1?i<5fuIj-ISaAgKo;SVKr%S z2KHJ%qJYY5>=yG0n0X&`iYb+DmeXwze#Y*?$>}$Hqs<)UDVubUc5Ak#1dnIyK8MSu zGF#rCq*X2tkJKZ@8fFY2p)u&qsvOs~fKsl^dUwhWYY@{<$a2f=JMY$!1$z2ZLd31V zyWUXWs7KBJ;uPb)RNODf#ve9-o?iH&7kufI&_M*vhgX#<5gR=5SHzD5<2P0!t0MQy zU+loPT&ybucg$A5h0@oYxk1~5iXA-Z>hKeze;C(&9IPX7_ekOP^zO@io2)V86KD?- z{p*2fh4wSUHhzi|ArORIy6M03+e?#fZcYtsE?u*R>IHaRU z+YZSDs8h+8t}q*c zGA@%}sg3)vy_%=9Z4>q0zS(JrdurCjK&!*H>V1v=^wMjNm(^C-vHd##6!*py*Jhhyl4jC(0r1(jvJGlvy7v4Y6FE!s)1XKgO3J+7U|2@IERrELa zfzlx;>w(fCDBa0~atr$4(f?ot}(iS$qxXgbTNT60rf)M4rs z-ol>+Zu+cJsEn|pYy?cAt#iq*v2O3MWd&*zJGN#Wtp|G|3())_>?ZXtd(=%h7lSm= zpgK4JJPFHH1ZWy4di25U&3o;7fAjKSdMGUqCW=8DI?w?BGl4$?WyAkw@DR)Ywuyog z`~OaW|0~O%hce;+ZuD;@0NnZ?rGWoxb4uucX1%aJtn5Ga0;rLdxMVqg_ZXB(?y}k0 z8Gkb#fU@(cb~$%@Ny!2$_``w_B7JUDkBp=PQT**46k8DNy5$zp&TdEe!{)V1n?q1P z`$}pC{P*v|eA{HYY?2s2Gfu>~0AiAo{@cc>baqXLIi(D+?S@m#rd+))DY=quCd)O4 zI+Pg8XY4X6fx_*EaiZ$DPf2LxG&Lm2Q>yzZBe#SxC-h6L*NpZAt3Hc z2Mfq}bp1~ET&Z|sa3f6x6<9$Pq59AgZCbi09H2z*WD4pGjNfzbjiC7MiksEa!U9U^ zRe76ZucXlV9s7elGEOtKf+pHS9HPvVX3*Xjc7URfUNUW!&xXxuU`kW+85}ZgMLh+# z#6kvH?x7l}ny5A|k#vf}FtD)A%K?}kka;qc5zb;l_y9WCp7R+FPpKgRex)qZF>(4} zfbK~VwcZ|@f_-#pv*kWzT~CZ6MJDtyQ9n}1@sf_+uVQ2w-_XEt>w>aOUE!Pih4!}& zM5c7vVB2KeAWD@i+4dlBnNW}1TZe~X_ThqL`?J92Aaw-nfgiYE;{6E{i zPm4}HeOE9pBG~w}1L2+SIO$r&CY`t0d)JsEP;Z;LYh!tAdT0|H;R;I3E#kkaZb7ckj-7FSFN$G` z0f*<&(v)EnEM_?90pNcO7Kb$sBwAp00@lrYOu-zHL~3%wBd%AEyn=S#$&nX`G+!s= z58H#oLHMtDoD1y9K4?bj^==&9?ri{DKJ_Bsv~*bCknSI&OwhwVPL8v+FKm?cxa?8H zZkMB+s7nR7ik)))J$n-2EbPzt&Qk%fVg~ES?lrawXy{CW>w<9INW`zQ3YO|IXq$4h z>}pgxmu_UWa6$1xZ$kaG&yy%qvP&o!lL9veb!mdvoX}PC7>MhGMXy1^aN!f#%Y~Iu zttx8y`Q*xN7|h5h;)iu<$q=jX$|~x;=%TSUc=jMC2DNrjLf&PC8H0&VaLT#;Y9sWw zm;I@+?z(CXyZm8Xv$I{auzi@w;WHXy50E5NG)D^4G1=yLyfRgdtm~U8Vs`kjx{v#57FmF{L zu_Tt4IPe4YtYLC9d68|>{{waX$X7UQlHyDKat4vp=CFYYS0W8`uRyaz!6sTCb`z6P zqdUE!sSmeN^%Y!KF7VSCgHRtlTxIWaI+C>9*d0BrihjB%thj*%z6%#1g0DRy?beZn z7Y{n-aaG-(`rXm+#g##9em>W%fjte(I@-u+*(5NT@{r>Iv?H+I;9)!>%Zjk&6~Vk~ zzXLn+`A?y!hDiNdvAnV!t6a6ss9Ue>xrF82MrFRBq2DN_u7gvw;AJ3#h&c&W^+KtE zlf>0*pC8L`m6}~WDop7hoV^cAp1$a1a90E!=r)cd4>P}|&Y#B-Ul1hD6VXAQHjc-Z zk^HyFGODX>dp4iFgZes}=5>(EZ1)VvxSCo2tE^;#!(FI4h=tEk+`!pxGnv3F#4V?7 zrR6sS*&L8kXm92MMM=;r+IMDKj~u(7P3Vk+L;dy1Y;r*VdEB$Zh>88)o=goT((gGh zBRFGy6}!9xyrr@a%a1IZZ~GB32Y376UuKAG=uB|CVRghP6$-hC*n@y~RAn;lKpb`R z3V^#$KGTuf=`c?E+mT?iO)e#T>I2uVK=Y@sQK;4c+{vIK9>=^njmkkpjU1iQ?g!Ii zJ6)yL(ESJ<3aa|BvYFOKOr!=A*`%_ez_eGL6OaYnGf_c<+J~_|6LDDcz7@EPO{Dh0 zb7g?tJ|vm856tT$x{P@>TDnLlZH3=K-6A72L8h;P@2ENb%f4PpXt9^`&uc$sA$*tF z#$}*FBuysxtkU#%)mYKtn0;{QACe5M@YRoVKjJPOu*DAlhOWCZucjsZze0a8D=7Ix zw?HwK=`-B-y=yzhLIKMqtE{Wa{uU%ntt>&!lVm0UJVG`xHs;kz69{KBF*1U7Xhrog zM1bPWI=wNiifjtdH7xH!Bf3vRJ5Hb93TiHi5fcUTShb)#ya$UzfSbEZ1En_M85*&I z_=u^?4hpE9)e$wR0<+<3j?RxXHC5hauHHfwMnkBPS!Y0yj5^rcgo;P9Ja2U?A@a&> z9BxEt&sZatcUn0OC9U-?jH-glzHA`Wj-z2GYu~4h>p^uT%Rz7ue$z*MGA!zh*!oC$ z4(*JP&SyUN!F;2tBF%WAZ(MbrD<6u&_TIGX%LnXj@T0xKLx`UZ!JEfjY7s@N5Y zxH?Y=99nFGPa_yr`)DQ`{k_|wxh?8E9UnRRA2~G&A=->=wCI0 z!KA3j$Qq`QPmHTCsqX|C0UjZ8cxquNJxj&0agapZn%54%TL;?e?*o)wsKCtiD6}t8 z3@I3R8vPsB;^%RaZL%ql$A5-^!-83gN?(^2i}J7B?j)2&n#SovNjo)+pC}H+5m%WYVlGGzO?0$WjN4%9MaiC%?-b1E_-HrJG2i<{-vGz zK8_vvc%^4C!L;nLTVhv=`6w0zw>oQfysEb|NxByXg3#_ehfuW3_!66aaA!ETWOhAE zI8;MUSHJQ7^qFf{OG~0+;RPynzO%=oprZNBr+sR>S2;|7c6ZMT$-WHr@U5*qceejK zBgehi%I}vMq^q6AhBj~^ZZ_>z&Lc0RtYigVv8g&kU_Vs&Fin+pk?me>MZ zP%1YylKB38O*&*O_Dp2$cY?$-0sZt;77v$B$!`8qSPjt;T46^cd}PEAY&0FhCkgcw!jie z8i~J*3t#8bWwdpFB$_}4e!D(6&Fk);ccYbUb)iwKS*5*tLo6vz2IgU9=bw#Xmt}`n zewQ4emB`@=#eWz*)NR_L-Q+&f)+D!tv-!78-loGbtD$s{HRrWLb{zIs!^)2WP(t{a z1#%~ATlRO+cH1p9&g1MM)V=S1J5FO2#OJ}IOC?#pLWLvlOfMLN zWP6veb|gH~i^pM`pRAFyIosAOJNf0hFy!-c@;UT9l4%ILx8}~3$s&h$e4NQkE;5@- zyGxO`V|mw}lXnU5vu4wVrINBf8(-8>dplumKECp^&@RVu;37mpCV<#p2JEbjDZcm6 z?m8o8Uh)aj*H%W8Rp%DY_67JKEaL1ln(RBgWOsL~#jX_B1V;3W@b0ej3R6Bdl8?AU zph{zM$tTwZH#qdHYUBU`HY_AloP+{g%sU?lm+y1V&!1QVi9b0Cd&Z9LLEh1#)`QXD zvOKsU%!0Z&ROL>>UWM1%&UcUFbpWm)S~hx5a?`@ndHKDMYtr=+xB@nlJwPu}>O; z)=bZ09yHxN0=QEZ+WnTNzKDzXZqB?U3B7PP>_aj>CTz7(TV@f^GVnt})Zh?*;V)0y zw6Ugjvub(iIqlT#_Umt`tNfPNuL(B?BA3MeIzuqZV{yl6(dwBb#-jcer?b%aFAR;= zH*;ICE)p%k)s7#JHr6Ba$O6r14ha`n%bU{zM*?=1?>>;{)SESvf1 z4PUZ^+?XZL?$JmtZoEY+`__|`iM!V?haD>eYM;+*L8^NPQr%eB9A#BvQgtd2T@~S8 z!C+-&v-j%li~44A6)WsjXk=g~q#xZ;!s7=; zs&pNLeXu8~=7ox6m$hzMR%_-f@$UrF5XCFUwL?~mPl-Ei`~Eqz0z6)VD%FPcsJ0lbJ6dL2PG1@5x2vK{M-DCe)SVUR z)qOf`%cBRaTm3{ny+Adbd0PD2jDe6|q~Of zQ{9dw$U&=uJ0dT<_&R4f61JJgI$U>W|Mf;oIy<1Z>3ISUJZf1vS~4~@p?BS9!^$Kq z%Ky_LV$fW|*fd>ky|uM-Vjx%&mUr@8Cu8N!STm8O?j-L-QL|AD5|{ZU`UiQ4OT_)b zRQmyaLU>!QASZbiY2e^XT#DN`V&xEwP$HN#gR!?kpU_{q5KXpkF1#OupqJC9hgD3c#A8!*dq#r<%R0?C)J;rqiUIo9`ID09uCUua~R@K_d=_MpE}7dw-7 zHTb&jvKOJ-{uxyTtaxnk`;3_BoKt|!KKE2qn0C!ZTmjRPi^=!uByAD?p|KO(fOX?7k0ddA_Y^{1km$|1Jck56PhoFqj?^QW`eF$h_xE1>&HGoZH zoK$c1?M2CZ@6G2#L9C3h@?)YI(ZuuRgBdD(yWq^FwdD?Q+rDDMi-p1r6%L`=q3mC2mT1#OIU7 z+&$xi1tz}Y%heZ&-Ov7-I-3kvv6+V8-k0GM#KnC&9(oRqr<;a8XxOujVyRmm0pljY zLrx2Y4k>teu@d0HsnZ00LT*_uhpweD`xmrjEoYzEkCeK zAF)aH%)TgpE*;?s?KW3Anf3+Ccx_si-w3+Mj4uy7w*p8UyJ#B{MrFhEk_GOu6>qg_ zA=v2cuk;o7AR%1>Y12^YJ7Fs>-N|w>wn08k&$;Wnjw^<3ucWDl_e@8fxpp&PPrR9{ zV{M~LjS?w<2`>@3y*yxou;KZW#L?3>zMO< z@8dTqH7x&d9)d}-R^wr)yKT&3+~F|~s4%FO1?F0SAXE!{8&7R~o}ttS)&KgC&>h<)D@)`@x$Q=eLxAZGeb2nSk27eL<|oYNP5k!4-3~ zeI`~7s6Aa8kn{7Agf>*SlvXA!B zV4_O~5&M&LbXn{KtPi}2((XeZ zgFR>?VbRoGdQ8 zW7d0jXWtU&Sdv`Uz=9#F@UHk82QxX`B>+00^fr+iv>-gbj&0mSPLPGsh|7OT;tf&x z#Pwge54{y^(1R^JE(cXHrC>u@9R2c zP%*Tf7)qttUj{=P6-u4vUo~GcH~Oq?v%Dl)V)shH*H=^Sq}(RYC7NidJ4@Tsm~Zkm zU#=E1Pss!>CZS`+C{;-=h~yym#ZdI_MHp-WNpjIe$u{m+gbTbDm))zie zNu4Wt!kM5SRQg7wL=!PWQZoHWCAs~0st9zf3LOrvB%uf1JaDlz*7>_CmTw+7J)@Em z8}5K4*i>hC$28JEFYp|7&{olUBDA6CBNgg~l^bc11T2h^H?+jMiG<;JaK!=Mhhl;4 zm0>Ebjg~9*Bb55FpD$^=O%hpwPQksU%9y<26N>DRdPD3Uoi7~%_nDxxTCl6zs~To# z68c$`df@4#)Mad~8kzR1A9VMiE7c76@ZiRvbUo4x^gqP_Afm zK!aQ_i=mP}Q;TrOdNd?mTRa%Bj#;bC*L-%TwbjvlJX#pwwsHJMl$oqqvS!T_%)8zP zmhMMvi~lqI99#iSF%iA*9`~`F?PpC1w+2*({S&!Nh-OmC{OEq|{%rs)3`#)m zV(2bdyFayf7kuyZx@~{0=Nxc6uTpK9ez;ZK<-`_2579Z$b{W;3cSB#5Es687XjSt%HfbFJ)(a+B~@@$p%HbaO=|7eLm9GTtVn)>5Ruz}Lu{nGo8 zNq1}}HaBu0xdX`-baffK&SjH{t%Td7^3ut1)Wa4ZJm7u=r)-pBKaOG*JyDfHM7lzx zP-8KrQ~|&t!2!}ISV;hR)k`C zFyLdM6Omu2gdic}TEe54$1L~vwztIsyypjFu>sfix=q~R)b5{e(AGvi9esS=u~e&6<6{jPpaY*ttoj{OZTnu7(PQ^>Od3 zET1jm^|Fc%?vU4KIAWA_3-cRI6lzoME`zA*tn}&IxTQZ~I~&a*^6`6h5ANHpR@h9m zj9sg+pBU2)#}kN+shhCIeuTAuhpY3NoRqxtMbGzv(;u%e@8^SC20AG}-*P zvewN9ENBMVZeBdE(tCbL|E%-Q^6gq3kFLhhWpuHvF8@D*v^w^MiaA$|O`1(hZ^e!p z+FiW3dEXu-(eI1_6#9*heyOw(ci0!OmB~?*aa!NGs!;8Ig9K8FpLw4`aIQ6S*B>AB z+Kb}mHi|>KT+@rS$Cc||t|6~jgfS}(D`!lo?p#;yopA3EC{i?@|FJi}*RgZuAcB1W zPNIkTaNPrOj@PQ4F4k9;W=00tQdCCig|uczR0!mBp7Any$MLbO(+RKJ4DP z8;HjMxtKSiC<-?6_bgJek6jILLhy7|J#(+tQdz~g)R@rhyf&=nuD)l)T0Lhq_o{j$ z$5N4S%>XQ;5~s7T6)*+5?{gBg*<3iNMc;4WF$Go4V`5DU7M1xmBa~w;7%HuRjn`JB z65Os}@{xc91Ai_8+OT0~A3&z~7INYct~)-hML&Zsw~+NM3=UZ4q=SZw?oWKhQ0>M} zH(qir@Ipo$Gl4#CNk=T0~cGAw+Hlc@ehYK(g@#<7D@xYBsh z$%JMQXS!?jXai$(v}HX9380#qZe%pXVD@&77sUL>68X4t!LAPd>ICxs-mun-!8%NU z+q8PM+8}M~>d4uy%KcM#0%0)Y4JrN^FIy&6$$uz{q1yZd0r%_K#CqSAt{nwuBJ_9yuI6uKtgK&(Y&i zMRLQj6o%LXsU0hT=;Lj6E83S%uP z{*m=t;arqQS$%_DBlCSr0f(aSz_z*6+5zOmynQisXsq2jM?!Sxn5uh%?&i`BlF4qS zxjWrRK`b90qkN>v{~dSIwPm>fvj#lw6#N#z2)PhYgAwvsE}_OI$v8cUo$hq5H(Xa5n$)nN1Mlqrw{qesZ@unsb2!DJ%ul<&up5BGHB|IL# zx*FX+OYV?98>6H`LOkU3HhYPeFALf-ZY#`1z6}~UCpE-42~L zdxa83CF3!*-eq0xE(VYC6Yf4Gob8KsP!TOIq4c&ctavOwg@pUtOOo^mQ`qQnBp+)j zR`V{+6tp#6Yi;Amp#BpVZhiaG5?fdQanG~`8*{(%_R3&ur)m1}U}#sU@YRNGI zOn)>T8uY!*lrl4RCGd+@xv$bO(r_}u)L9qfPVLyqpPjFE;z)^3GBR+VGt<;z$z0Zw zLSzd`o#oOUd%hbNA|_gwyEXcYw@e-6<=S*s;0 zRG}J$^~pM<|LrJ{5BDa+ui{nD5RoOl-GJyP|Pd zbuKK6X74;-!8+p$-`pb0C+t`;ojLDfI8EFm;xVjplKQB57lneN#n`mn zyZ*cyKw_~2P5&#{?|T9!Xl~C;eKzj$zCzKFE8DA0ra#@<>;nfU!Or=rjm`Nr@X9-O z2TNVjT<>?a+Q_`wru^f6JYSkezblkHn(RF$`aYY2i+s`rCyj#N@;8|E?h9vUtTc^$ zIr5)TPVqvb{I3zAufqNVMufv4tOA`%!Rs+VpaeR#a@cIa=N<|=hyvjhNC(Ry%<@lP z=vx)YAj8-PP&?4qu4E1s2ueUFS0Drf(dZ6>!43foD!L`MBxgbkqh0_1sA_{;VsKk#Ufz^KMw6z1_qjT4-$5xo9DANPkPTnWquf~glS54jOeo~}w zjV|J7l>tV`Umjvl-%zq1z<{(EchpM`nO?QaTURW;^~~d@ge;y4Law~*bPyEo`)0k1 zOk(SRy^h=?R-TNCL}EtKgeU5y0zkC3^aC;FFjMgb*m+2 zl(wQP;?`p?5&W-ZBHJ6J_cx+0B27Ice0({F^j{=`J=zzkh|A>u9Gs~9AlprpG>U{? zzPMtdrJ?Z`?Y6VvU7kj;)mY;rXORVM{?*1DB>@{RCD$3VP#vb%wVGD)tU1VsU{R^s zp_9?1tjN9RG}S>*=ZfO`mK-iX4FArf+<%Y8-<~9>?M&=Nba%h4%D+p&Hvu_&R@~+sQsuiO;gmPL^Qt0JAU&3~U z+}`v2QFg$PWuO!J`pX-%e-%+%A&B}3V_q+D<0DQ~RV{jJIjURkl>Id&y=wxgE%zOE zlGDz1&y)I8m;?+yZ!Vw_G^FQ$W;FWuI_bN(%|?__feA5`Zn7IQl^UPu)-6=tQJit6 zV^2ImkD#RE@8h&Az(&A%6z;gMk9ib&(4ky5oNiG` zT|nO3;ZT3L`=ctJ7dL@ju7Tqj#CvPrWU+RpN*Qp}9ehCE)DJqp%Zr-*Fc{u3CD|H5 zji54>R6v&+N`?w(42nmXx4`3V1ZKB^2 zVRPeBk$Sosih9r}NRD4I&=BFuRgAHC3{(kJjaWQxmVUgxW0cI9OSw?LGBs9=+PbBT z8vavA^KFsYZO#do;@utB{2cFSd4jiwqSy1R=Vi!s_I?IHdANjIA;Gu&vWAzuc zyw9=;8@m7eHdHBWoLVma*t-`^Xr6jqTXDS7+wPf4;!{oEH}0=pY%0}2HSloitq;<% ztyl%+tl5ySE`+hQV~>5CUlj};%v zE9as`7ruNQ4qB_zk$NMpbpsamF4>2R;rfkG#o1uDXu+}EdkZZ|dNn#7CzPY8?<6u= zO`Qr+h@a zH1aAN_qOXPD;y`Qjw&!YP2`J~P7zf{jLE5_^?N!vsZA={&m8b@WAULK7rHzE4o z{B!vv-^WTq`O7gu)|6W7c%e&_PtHkeH%}`@PYO6-)KRy$w!!gxSQe8Z^yuaLHnqhM z?2PSL#x4)J#!yEy#`HEK-bB;0eyh$g-9KUa<;@UEB~cv}6Cqi`-;3x)K!NEvbI} zx%a#SubMhmvAq;>a*gI2Eg3m`=J5|Uw^>{z5W^$=P)8&Ep6s6=Um~c}(OqL-Xy2P{ zWO?$-OG>46&;WAWKbR5!S>b9m)F;f*C+gSl8#2Jy6}0rb%x?TYb$xYQR9)Nd00Ig~ zr=-$KHwq5jAxI;QAR^s4gdm*)l0%0|Hwc3uAR;9tEj@G%H83-0^Y}jRIp6u6GxGygX?Rb%bMoGGT5uesMF4tKm<9@ACV3b;(IqI}Ru7KucGVSqll?OQRdbm+Jr=>}7*lRR0o}aH~X};aD20OvH!%_j#C&1Gx z@Kj4=(LH&Ts1u6o0wX{Ut~-&lO-U-6PrqBMN5a7!gM~0;$G^3n$~qeTAeWAW>XT*H z`B?@v#8ytpm@P18u1Cg|i*?L`=SjbDpCX z(viJ?R30@mFppYzHI__T!ewzE*!nt|+iNKF-GRF}%HK~`ujqQ~FRC!OLS*9*@>voO zRW0f&l~>-PvfHk+QG30zpId_cNkrpC(1y)aE@|)6&K91#ZyJ3iHhdHi2e(=aJ&&X0 zf!&0`glssoh$S^_LeCB-&kylvNg1;R)WSXYLP#OR#KdIQns?0NES{3D;7o%lUWlI7 zU*m*`4Q?3DqTIM<{f+Qg?)Xc65z!@C%G_o46GH?iM?p2)SNte=^(Z7qQy!Brl0Uo{ z&JrH9Ow;##DCLv0oH>RV*?z?EOVi}(b^l}^S2IO(9K3pa;m}cT7Q5vbNvJ~_EjnhSa&jUMp%N-c3ha}alSTB$3p&>c zvv8SnIk@DsDKNqqtK`D?=4AhJthcRfoC_sWHn#yn2 z1#bn|r*jj%iAOV7MNE??SXjK2ndR#|Ui#uD%xlkd^|w@v5&qkj5ds~dR~LcJdxDTL zJA*9+yeoHEf|_!lnI{pIKa%16ZM`+aRTj&}q4bkdf}BCoQcYNE(dVshgeOXvauofM;czdbx)<0uBOwva`6^X=!8UD5CXdRa%>5N`q#UP z#)U9}{*Cg0_>@Oov;EJbHC26DHn<~u#C~CptUB$Y@SSI&bug7dZW*gsmKO(V%*pq5 z@EQsa4dP{dZ0G&*VGd(+`$+*~$ygQmV-`ZI>*4%I#$D2#Oyd8ZUR_qRDSyVu-DA z0Ba!Sz59E)=N%>kP9ivQUgqxc+;4cJjl|-#@#^vPkx3=B`Sek{>|553J5##3SN-4h z)Q+&HrvtBKi?F|JOsypnq`uF0ZPjnVo%$50x$I&a7R_UNo5Fe{6m4a1vLF>7ZNxlg z!IEB6#G%|VYK!Ra^cuH=W*8^2xb@BcF^Qf>B-HZ-*xf2EfV^Vc9gLa`{;bQz0ICVD zf{)-5^F2H!o&>L$KL4Ugu^NLG(}q=bB!v>0tl#f{x~N!Gs^4TdrQB> zTQKMM-u9&&o|0qWd;oZJk|>3lI3an8**!@FL$EL8yP)C6KFdF@on97zN5N&mr2vbW z9f{*~?a=JH@A8md{GL8G%asmHQ0c_dS;3=C{cK%X=8jImD^Q5LBu_qMQ_SK?Aw3TH zkr)#}kzLCf!uq%58sp~h0aNba8P%nH{=H@2-H>gXtf{1 zEySk1%v@``M4f5QR=<$=-a~$x?XJN2)8c6mc#FChnN>iDAY9KaVp{CFx0-Gt0;d>- z=9HaIcE>SosuySLg>IDCcql>?9bY@pKC+9SkgtMd4XxaPAF#OM3#-2;rBn*f3U^T2 zqwE>v8TFyY^r7q-ohsVG(Vqn|jFz_Fw+66?W!HjV(Wy>B{^O%DNU7VQV6*dIHz*U{ zUJ*6lZk_Y}8mz*;v2<033r8tbwhrDVjZ=W=rnECIX8FJi&kqSI4XRNd?$1IKAu2;bcHm#=5Ez)Y>Q&j)y$W8m|v z@n65FEu+x_qdW#m={<}0)hr@zabU#}1gq0*sHo2Th+23^9EihwVf@946y@|GBIpPi z@!;t^a}!&|#;_-^OOpNf*lvn%Qjw2e!Kqs^)zgwQB5G4RUcjrXaM+HYGcdHaCZZ`9 z^N-7(+6n%!zK0ZMjq3a^OE-W20XxHX!bCPsiLqC{uB<^mo1r!{%8X66sxL&sU#Ucx zqmrXD5xw|Ws*+{?9HEN+bk|4}J|d9yx*n}oC-6nTjZf;^WwG4FZ3VZ8i7U9vpUx#l z*dO1-ulC`)PlQFA25%a~pdic|aq&L|vidqq5477Q*s^hiVyPh5y`%W{!FDnZKIM~? z9}U)BpfBIWBt?uJ`~4*SeVDefdDY2KH*<#GAh}QBM5{f|@!yG$em{<+%@(9WbsS=8 zO1g+GYnOeX+O9fP!v5Lu=h?D53&elKC8xBP(tz+6%`Hja5A{<{QKFmqae9(1Uy*Dm zx!{ME_d-eCusywJjRXrQQLh#KdAxc|O1&i23n9*zW&apzZ;XxFG&xN8-O2d8oNf&A zCfffYu}0Oe3M=8@HCJwzoeW|mOb&=php9txz(c5|$F}KBlT`>wSAZx;d;`aE*IeB~C_fI{Fr8`3ZBrWqI^;5C;*13i z#7GJp3WuhrH(9FRT!RZVNUvLFEbz5~gtY&D)qxLUdB4u^GJ;VxZM}v=!bE ze|@xS)1pch(IdmBC$!`9+U|a2c5TUo53%i~_?36uFAdT@w-yYNWaK@o?_I|u@{}nG zUtHeG6z4leMu0NjoltHO@yoS8iC4nx^s@Fp zho|l9x3yLM57bFeJw!)W{BR{2V@`svv$w}xm<(lJ_gc0TZSr)!?Zy;U{nbP z0^6x<_dN_$xHNO|fnLW-v|n$F10a4GWHYcUKR10$7VGlPIqgaq*r^44BfdofY?T5@ zmWlp*rHT9}xH<;Si2{K90Ja{c3ITXpDv&L3<-b=hznFmyWWZ(Tz$WP56#k6|0aE)L z52Bok2KaUWj(({a{P*{&+XmbBY8GLg@!f-3KchOj8AfDAqB5@1Q zy>q!yzVqn;(DgT;oX{J|j}e6J;gJC8#{>NGYn$f3Y4GbJ3@h|v&?Ss0mn}U@q|CF=R}QOm z_fHx|j$OqHVd3ac+C0M#5bv%Iu15z@K^%Pg7Lc?;4AsMX@k{^!JLiCr7?)Ov)-%Z>0zsW9URY&ouxir|3 z$x@qzTAOe2UfK_4u_uEXe>}-fEu3g_VmSDGPf7y^-R;H18+=WA8$=YpS`g-zX*C(8O zhZ>zCB~qtECTS+fwOcLhbjlQf=m#5r1KWNlHM!UjhYjppA2?QbOu-LNWY(tB@Kzt*}p+qrGv zi#n_J(@R@GDTeWc3!PAE9GT2FS#1FwOES!Zpf7hQ%s=Z^P@ zuTW(a=@}p&oF$HPEh(!^Q|<;A9>>5A^YQBNWf5%P*r8lA$!@!X!^ z4*6Y=8|KM~fO%{V!!W3WygtM?@Xrj3?aM+1?2A_bS>vT{)Ye-REQKh!!eyybI#H@W z5b(rQV}@D@P{1r8Ax8dkb|bjiMfsQ2Cbx9gv4zs#;Y1gFVm%<{$A)V|)w6z(C{bJW z6n3^&ik}v0IZM3HPr1PIm<#m&{vr1+`{SP^X^cV6a=~xuq6#qm0RT!LoSKAw)V)jI zGMG}SBSuk2j0$Rjy~!rq5!*fExy(L`WEE6|Faus|c3I*Zy*z+m+5y@Nt8&8i#cCqf zGc13kO&lP^^1$~8Lp~rHBy2zYYVuUwT`ka2ni zMjs^t`Zo;V;K0Fj-u2kepZizcY&5_Q&+pkY+aTa$PO}YU-Dk>>rl$|hlMpp>5d`yf zZdR8urvX>QI7K3MKR*Ci{aH?uV|85AIvMy~aQY*|;iu}gdJiWXGYVmaU_uPrS?vpK z_~x6K#j(aN=QljD-RbsSU58#)&Y021pmtWHrB1W1ry!FiX}hPdkN2UsIsDk{v`-1M zeD3=~5ZXny%t-!WvVBa+>2fO=_zVr6+c%DqZ#J`SZIO`XV0Q+q0@bJ-5&rV5g=Y z32wf+8wYuWpsee4hO!$ZcRZn%XJ;F}C;72wgG--nV#r7!C>- zF+gVfx>JHym{@Ux+Wx+c%)~)KEa83F#+W7}b_oH>ZGoHa{JBA3ljc8fpaRgGq96S> z(l0DOd`7skQ`a5OK==!hG#xa$v^QCA-Ai!t>Q7gw!RsS4n$H2@?p%}rwFcHQ?|Tm@ znyA z2g!l3nWU5g%rH*>KW#)_x7T9GMjV~+=LSXlu6b%+laTKhOBrOXV_?O&-H-a8;!ptP z>v}bD?`yU5z&IdRl_aDRM!>^AFwasCPaIDW^v0AuOSw%K4#-x`j4^KpHwz};+1T0` z%H~Z|^Wwef!(ppN49yHeUP#*s!Cc!+s42Nmmgzid;9@|vYi-5WAW7r#7-Z|L{OEGo z;q*>#Ld116R8iwD&Eop_cZ<2pN+gBu8*K8xmZe>li5$Hg-cEFcVu4RKv3DwpLcblR zTMf1MtCYpaJ~w>*q57uq9IgrGM_Z^pK10YB>M#ySKQ90m^svi9+z{H@PzYMmS#blX zrc)I;$JKbq!8PT=ct&gc9$Hc=CuPiRqvIpw64&3xxVM%mv&7AZE{!7HQ(D}IM_}4C zv6o$J`U2Bph=Oi0i==7VN4hfC(f$;^<5Q?TOynKFAgG^23&MOs#|KiR#Aq7i!$?r! z7n~z_qOJCKiggj36<=6&r<4&xd7X@5>0S3^zpda0xu7<9YFO<8> zUf{X`Bp5xnQm|Y13>F6toie1rc9^i9ucRa3ysao{0SgbfWpXlNfas%lp$+HnypS8i z^!>*iYlz!#p>FxU&MB>jOa|xdv>92O__v05xu3cr#W}Bt0o9;Dlq5yhqD1S{iubHN zDsYGG-USO{age0X~pbt}t=JTR_=3_swK#n)~O28g{i zDadQNiBuzEV5NnayFiH?v*-zA-qEMkenDA37}H)s){KTUlF-@=pdEg$ne6VhUSr1i zSmFa6K4p|O@YF$)XTC#c@zjKoMPZh;oG2(amjOcC0&t)T8+QI+Hw@=9`xUx7g0R90 z+tOK5Z*VLMB$6iy>BZi#+$%8e@SiA7M8}0|JcJiyZeNrG9MxX{Kbg<0jnZ|KmyXWA zm(CU_V1T2+grgQR3{fu9oC;baQy%gzcL{%lzDPKJHqw2MB6i?X9u$INF(=+GOePOR zb}~i0B}?V`enECgsYP3(_VGICXcr)t0;AnWzzl)eknYZz7olD6OU3l&m&`J3IlSCw zWXr8|vJllHZo0Sg51bNKZ&&K|AviS=%#S_GzpQ6MC-(gHnw=N)q>I6i46D9r0L?To zFt@*pv{(Ep?J(TO<%XSM8YRzSaK9a3m|}AK!Y7uMOMv0Kbpf(8+nL-15Ghlhx+iuk zFX+s;e;%Zq|BOq4P}f0)hUQuw=*dqU^4Jdd+Yf%kbiPrh)n-es5oLPfZBu0&mq7%6 zIhcN`4C%&`@k^3sM9_@U4TP|bj&x$>`mm{J;-e%#{no9}n|>C9jzOE$flxZjt)oeF zpOD&U<^Z3NWdllFOJ6E8J@HAipWbyLYcG;m-`_4L{Z?@dN@fDBH^ta4u3j;8B|VuI zfL-mUE8kt1R$}0Evfux66x~qTo7PuLmdB3 zEdP5?{NH({3qb4s&lL6FTQ{nbf2W$_{|yFclK#Eb4E{G5{T9aIZ>pGeQ->oTEtd-+ z!M>=d{?()Td~;0#~80t%yc5u{W^D?zEcA*S#Q!K{Nuw1LLQ-BfZ_`rgbGSsf|58~2LqG`FW&q?0@)94DaLtL2$sN<5lETb!R8V9fMi+P!&ZXD|u)Bg6}!uS4grx5Q4T4jwJ;?8WCUo@CBn5BwBV z`n*WXD!g#AEdIm?r1ONb4@(MkTR=tt54%r_ElQO`=00h(Eah$NLIUhtRBUW;svpHF zby0d)-16xuppW`z9k7Ie`RN7c_KvH?fb&z#eetWQVIQqe7!x0h`$!9Ob7#HZ^Yc=Y zl3zi^)PN}B>vI935&?!+fq`FOuqCgB;bE<%^Rm)XZy%o$>W2FI@XUVO9~iEL)p&6U znzvD7&@pIK)ELGCKrCb((?yPrjfH+^XI34bsN?BijpSvPRgSvSlw{~PHofB0i_2=* z-*Sw579?4?$8*DTowCQjm$dBBrHAo`As_fq=B|`YE6^s!O$B z+1SwVrTyn94aw~8?&r~rXmnXw*~jGQ=sQXnr5D`R2zvzQgV%BJgR5YpFa}sd1EA^_ z`E5y$Bj&+?pn$+LbBDR6wYkN`skBmu6(brN8l>i#sj2C@4-VCcaakAl_4AWW ze6^;n1kq4r=>O0aHsYux*vB1Fz_=Sm@oam0YwOOAkt0D{dwXj4v$&!O#Hm}UUS1HO zqC~sBx@vQj_R(_f=o@bXQgjr zU(%(N%&z&F`{@$()Kph%pO&1SoiQ;me4!UO(|_J@7TzH|TFx8QeaL!B&>@TMAI5b@ zmq5RSr9@AaC0cIz1#T4fD4}QcME3lMSz!9i)vgT<@z3t{pJoAPS)v|VOJL#pbLdwD zqM_nLR#r^^L6`2_++2$eUp2ke@6%JSw?`<{-P5|?E0uSGot*CO36i5GAMWhzEGDdt z3=cmT36`=11OtXf78jY06owR3mS<*+rz8X8BJoDFk}0TH{7w zi9sLXvjT-7hRQr*x^=p1L%CYp+Z~^RCj6C#HB;hYn0N#GKr*!$)upSefauB^jmsP> z0lfDi>+`*X!Zv0vUOW@}X>M+g$bmvhesJ?8FFxat>S}0YD%GjPKaQ2VCBMuO-vNUq zDnQ!sMyBq`>_P9+8pCEtZM>;7ZRmx3>K{%K%%As;o0&Scx3-d@Y~t>!-_EL+P_Ftu zv3qXKIFN9n6j6)P*zEKU2$=gk+Mx36K4B5V3P15zN4QdNS{PQu__hXnjhBJ7&Tv=K zf+D1ou(GJPfNElK;dxN@ZZ-Z2sZ)`uA~2*}ZMezqCwO9X@3*Nomcxq+_$}M_0?Qvw zvG%`*cNTaTVNOo!*EOz%gMeC+IhI+jz<%jvXV=F_oX2Zdz%p`f&tS#jB|sbUEGabt zSC-mJ!2X3LL#FLLsvlBMpL%DdvxjjY)%(66K@Gqf_b;d#EiEHl+x?Jid}L&#!ph3( z>uWzqx69~KjkcE7?;}MU-nGygyU8XDU%$bcgm76hmxe)A$3|m|0AJr4yp5(i+46gXgM*pF_klL3 zm(-eqah0vv)5k}A$=btX{C?=?l9G4t-YGbvc3+UAG%XD@Yhx3Wb5chN8NO~}ot< znks9bI@Q5lRJ>=lw_o4*>&97PTA$$j8f)iD>wD5~{=uZIBHEPwZaGQPcgGxYBs8e8p1Ai#B*F5hrl`~um*Qbzegv|p!R0O z>4may=)G!;T&g0Zw=45EDS`y4tV3z`8~|Q1y1Bi{BqD5~Aqz&h<-Szm-^P{8f>A{W zS@tsrq|BzJ9IOwP9+ne!zySpkA?hnCv^ZhkV)&uC2jd;Vm`0~6Rwd1_i8Qx;yPz{Q z*3L-xF=!LLAs4Bdo^{G@Ay|F4&Sl)Jxw)ATzO)O#S{kOqeVt;PTLlsYl71FnB1v(C zGaIFt-+e&YgjKAB3q8HOzO2XDeAw=j&dW0e>yW4b4l8MQS(SLe%5Kkin-A$Sx}8!3)Q`}oIQ=IoQhP zM*0J`)#t2JY{-lcYGVYP11guJEt6%5OA8Bj6_3}N(!xrX@gD1j! zgw}VVLZb?UJ#zI|fgE3Qd5|Q0OVqN~d8~d5v?)uIMHv57?J*0C`6w7Zl0ixtRS4fE zK*oB0(HH#0^5+UKH!60{WcQ-7`P-l4LnyswA&l&{&qJ@*d35JH2KUx%DY6vHfrBn| z$s*Waqr~naclw`Q=ZhbB1S&!nCe^mS3WR-xkGw+qYeJ*q2;m2F)H>f^&Uc0QizryR zp=`bYn3iz#TB3jLZn=c&#f;rD12Cm^p6}w}#o5dw5fU!8tsNP3;O5{K@4r@3z;Fyu zm8F_8M6#o}=3EM4Of?U{ubu6%^4t)q2V;pB0#1!s4gpb7P6J$IK z7$};3)8MD^T_FrD=Ajypd}o9P;-s>4P`w+(Ud7$pS2!s~7lT=Z75f|Om z4%eo&S+pI$FJV443X7)u{PEUOK=KTGLiW|p>>&X0`1xl1q5l=y4enxbbR-tZVEh6h zuB5M~oOGVp1beO6AA^qK{d{cn>&P!E6aId0C6yBrB5uzRfUs}|n!+XFbA&Q+~NBrTA+u65=0?UJsJ0h~J44%4JW^l4(}PoN~mX zIpFxHaCFQ>Do7Ubh)PiwVwI5QGJVfa-a|YfeaP~WLrD`7DjF6-yG7v}c zw0O#8uk4{W*x^+7%N@I%$rsrmpN?&FPUE9T6LRGn~`uQ^>2g;pLR zMIg-|T#LoU@rxhJhqW^wgACige-3f~$-7W47`@RV@Iou}l*>Z>B0JOazB>EcJA%sj z5aY}#@q-jF`1b@Lf6BgF$*Bw*6+#vPtCxV~cTz0hWWRWnY`SK{@_N@&c=0+;j5qEPl68fGJ1~GH+}^QfZ`F_TG5k6z?sv3a z079H01umr=#@wt05!NOAr@EB|Vs3$GsxK)Nbtn<|vuNb~hqW~aF5L7q_q?zzuf|}4 zTYi>lsD{#Z+r&c#qCDS|;06 z?45DCDDp!xcy(F%_b}95q~mKa=Lh$houx1I-yF;p>h)LJ8Xs=T%>Begh$lVaOqzWH zywFYyf|p_z=`;6As$l0_m+iKr-Lb?mx?h^i+woA*d|8|qPfJ~Q6DH(R!_g`Td*qRF z9{BY7>n6!P=>bI1C%Ugk2i@nZREWevE+n)FOyrr6R=Zx~9W`#q8mb8T6mHQdpsf0% zGX8hTO1Jo7C@hw9w-Cl(YDCkl2g5#E4$fc`)oT%oZxCjR0%FHLs=h>9#^Ol_0I9lwt!Ruo~cV3b#k_wvrW@9%3q(SH)BSKHhV zRl_w7O)-&{MrNoMn#B{>p8r&=^Bo=mOP> zFKk~q#ot?mayuvaC!#s_ul6oNDWuas3{}GRRCq-s;mkL=Gcg>+3!} zOj*4nDsDrC(%kHNKAg&XG5-DIGhko>I}U%a)`eaZFjN0Y{h6QEJxX9?XfDNZSc&ef zChZ%IU$I~^4ZZY3!L`xfjh)sq$!?7t(xq(~-yL?Ea5{NH{D% z2Ho*uSD8awSr)@}^GiURRa9^esG|8Eg=KN3;~;|&8$n-WiH9~#0qc=@11-+5bbTO50H8`iQfU_Ee#JJ%b>6TRujN#ImMSjodZlJ&^Ad3 z5+@)1_p(Oo|9p;xSMk4}znT6U>A&%xK~C|XVVYDYnE#lgQXBL!KtkZNeVHN~iI|m( zD`FN>|J0Aluij$kzh@y0WtnPR>Pz$j_Ly^9FH$?YT!O&E!Z`sy?esgCqN@*}xS(ee zX{`@CK4t<;_=qitd#Wer;_;@g1SsUki?k|hdqCL$uN2eU^BBbs1yh4$mi0D1dQv?Z zX9f{}K<_h+W463<(NY)qAwg2dhI+e#sD)gB){d`%soEJnc>aa{2NFNT-3JobUZQ4L zD~u8cfyQA6SHNmO)l@i{3mP7LILQy9l=Z6om2e(NnbunV8?fZCx(xCe(uk2785e22 z5+IV?{D8Le_O^da4^X=Z;$Oe8MsDWlAMaOn8}5C&wmBCD1O_nU7HAEO8-o|sO0_vR zyRc){#!-o6M-aHP>ElKextt1?j@hRM{e_3Fg2MX#*CXoe)gLi05B7DbVnewIMj#1J z=#Oo;2U17m##7=$S0@dtU8lrjUe>PqsbL^;NGKMdR^r{hhnU6>5Z(0IWzx7IN3aBU=%5oC^hy$=%ydkmK$s~gkVnb|>I{p&?_6DH6$$Z+fQ(|br* zz-mAhpeq7|Jn`r-KmF|!Hx>YBc(-RZmOOoLfeR`paS{~vF+4wC?5Fkr^C{5}#ejs~ zXr2s>pkuWe(Tx{|sGT!rG9;F(z4G2FaFpoUJ}@d8?SRA;R3vJl571L5alos46YP0` zF~)cd2ccoH?_gaR?|m+DCl-PpIJ#MtO-{vWwar})t9_yfU;@S=$pwuzc^)A5pc?tnF)KZ7StMTVh zd=2z3m`n&FQ5!Ws0hw!ZK*Q9;yC$!~q(Mu&L0=P9_4QBJTqPQu0>)8CR?NV`KpD&6 zZE(l+RvRC22tqr=-}rP0RGv|i2`+@~v>}E$+c3jxFf;<66%+H8XzK zr1BKbv*N^EkCZ}iA39(G(D|IeOyjTwQr`)&xgbZa1FPNmT)m_#pzm5UE}$5nAH&9g zEF;AhNj^GN-8=6I*0bW1d3O4ZzAHdY9ET+bi|ZFVFy{vVW|1#xKm=ku^asFtG7(6s zRS;Mdo(F+q03g}_RPzpb2doGG-;&*c-1PrT3H*OV1t@_mC}7!EY({{H6*xll2LiI- zEN;AX{`a5i9skrl?pF_uUC-y!Ac7aqCwG^u4EW`d6DhmmJ literal 0 HcmV?d00001 diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_images/diagram_fab_auth_manager_airflow_architecture.png b/docs-archive/apache-airflow-providers-fab/1.0.4/_images/diagram_fab_auth_manager_airflow_architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..9c7a1d15618c007530e6a5f5a4967b2db66922f2 GIT binary patch literal 81735 zcmeFYXH=707d47{1Qieq3P@8xKzfs2RJt_jy$PX1=)H(2NS78mC{?5hNQcm*1`+}3 z5IUhIK!8vJxexC-@BPjlcZ~bv{(d(<5;BrJd#}CLTyxH6C-RNDBKfUHw}^;{$d#4k zw1|j^$%u%qW#1qMUNO9eQ7ODA|iTBq%8MR$2V(x&M!F|XUKMp z3BZ)=)_(hmsdIvzae%9qpPJnpDX*Mp@=g*PxZ|c zXd6mD8Dw}lHzJ~Ab#MJu9sU12C(81_dhI{YUReD7!VO>w?ZrsmPH(WE0d{Eq|o zvnXxTCqzWMMvr0@dU|>UeAnNc;xLH5J|+KvCXYowTTsXBRB@A}Z)pSU)-|F9Zbxh# zz2Dl$TAIoUL7$G!!E_m!a%bn_CN3hP1vPQcg%@?;xkSa>K;asjqt&SB)WTxN=@K4N zxUU{H5fNDI&|fOP+?Qv@2i?Ezhpo2T82S10XVzvl&=r@re|LmU{jhN+zI})SJ_*`L z{8-$?BAPV!l#hrAsTCfsxZii5Q;<(65tM3@h(;o{P45vAxn4~Hr8{Q|gGOPzsM(r_ ztJTqP70V;`mb(h~t`LFgyO^0935#rr4&13+<~emoM}L3n{R8=g>nf0f)_i71{kG2u z!&N2$tKGmlM45Hfy{-@u^~$!IA-XgqlXOZOR|YsgUI(H?Z_~3q)wnPMtM)pBOAVZasDzfNJ-KS8t`czI$UZ4B-!CTu5F9-p@PqRLNZ+D>8m=W)))^($=ixG+Cl zxyZ_Dt>ZpbE`GU%aE8P-ZOUlV!4837k9IE=qFA2Au)d#A{?8T0E9SF?tE#x9Z8!Ks zY&@-5<{Jo(C3>YN(^BSs-MHDn8G6H(m2Lg=oMyrvDGeQUAK@$^-e!2|X=U-YAiT;X zzW%-WIWK{~4Ud%x_zt^Fhwpl&hCe;+$DL;rWv_)@#>xtSymx|nh7iMMOOLfdkT`hr0P2@oK4o1yGXU~kK28dh~uuiD0JlE@r)P~>bf0h#k@E&yjc7tSq) zdrzwEXfL*gIPW)QgdIR>PSOe3`PC5oVe#nma!!4-pdC%jNiAVtr9{us(EVsiIg#R` z*j!an(N<4#&sX}uJmmS-ct!v6e4tPOZW~_1nG5euHOujGG#gMUHSeQ^_&ER0()1k2&xyR@6D^-e&@Y;#_&n#0_K>@)#ZTMcgO_}6q zo<cVH65G$xMODZ#y?W8I`%{DhoV~JUBQ4UA+IOT}eQh z<8kRo5oQV*&k*S&2}U^KcuNB`Gd|R~nX#o+qO(67AIMG-yaS!}#d0eKVIo47C$LMK zD38^BM>DLyiBH$e=-Al#cT@mZttzw_sD=5!<&8#W!r}0rJ`86Hy(C8%*nJ?N^>cghg9CL0NZ%}_ za?S@)--5Xe)RA)pM$V|#9VC5D6_OEuj*bwtMYm+tI2qc&vr_Cwi&pnJQ;S<$&yAtW zNj^c6AqOOFsr9YrYxr$myw<~PFFonw++cq5Ruq~=SrPR!@Fbe>*}pZ1#cyqct!Al& z&0}64Ds)J%A$epc>^%9|um;t#bTaFKOWo&eJ0PW@ryUBICs^4#IwD9ex)7@!l}M4p z9NU~=4#uL5*-Tr%t@I&EInmH#ZH3eP^p!VeTI?{Lex@FE z`QJkxBTvB@!|rr0y963XxZ5j0Zmk7pTwGKL( zXiPt{HQ;hCAsVL5%Wm{Mjrgd8!yzRNFt{RUCbmS^vC?+bIo zp6l=%!K7D-;0Bis!$U z(@D%Ky-$mvzPX2~^to;BVAFG6(A0IRwJBRY>yEr`!?TfSnn!f66>SyuBoE~v<{mqo zNb=_bl36k*$BG`X9iNrdkkyGq7QzxqFniktXIoa=G2tS>1-f%og45%y#Uo8a6355K z*BZ;rb5Xegb%qo4n8DnOVYdBUS&Fp)D1ju2W!`te(cak+HUn7i8*GBY;u)ott>|y4RP(dC?YU;Q zW^Z(#e5x75K6|u!Gd)E)(N@2#56HLtXB;V#^_%HJk76b3-9Zp@LY=;3&n8t40!RjT zY`KrMg{#FTV&8EdLcTQt!XTxzF|8Z)^=i-ilUB-V5b!$gp$FGIP(z4Id;&}Q68>ya zAPHl$yGNO$Q^S6$6Uzqh%MA3KBNtJRWzUfC3C8-0%t;=eE=BSyO4Ng8TqdpnZLKKo z=!lGrJaiP#uN+nFY9pH@_$ZEv8pX{$19&SegnIuu;HyUmd za8BO1o2RnBJy1M4H=5n?wZkN6$g9%xlha(anDYKs+dd5FbYCwn2GjTjl}AQ{4qnF? zsi&z)@l?dsx z4obY0dCyFb*aFCvu|}cZ(B$NC3C}h74M49i#OOjm`{Kep%{Vk~;rK{mE`B~_?b}@$ z+VM&ll?LIFtMOn-KqEoSIadTh}Q|e@uE!BFluySsi{gH%I^> zT_b>9CcO2AtHOQq!5U7(3tSljro z5Y6+Wn^9*YOAJt(Ll6Z8km zE7`^&)jBE|0H0;)-`}c0Af=i;FsW^6DwPca%I@8|Fl;Bbbbm#Jv43nL_^jxB>8b5g zW#N_EmJ2#1r<96}iZL6JOYqQ?H&Cu0ad(*i_hm+@i>lc+aflk{EbeK(GBEW@El^6RO zHCAUwmsN1I-sQJjidzc^*=^O%k6+_8NIM~=T3w7_7+lro(MU82><8HkJ@VU(>@`2+ zArzu=Qh`$AF+awms)2opA)`P==MqeS9AWGSI)A0O*+$Cj5gapM6)%}(t1q1`fjlu~ zTlsskO-)TTUa%sknQAfe{3w7fVfZdnL!z_QCq&G7XUA`52JGKG0rv0R5&JWr%f=9J z&_GuS6uk^#v(nbumqli;Yd#lqUNN&DO4!BvP56XpAaVIJ!G8iOp+~35pmZ2d8#4YZ_tf(k3V?+jUaH=m#byzMcKW;gV8n$lJf8B61Bs zjR;^E>?}lCqwy!jP08TWVLR*5B66{YkPt|YhZ&#=H2U1?oTsv~CA9VH;bSZds*39CQp?-Q|mXyw<*}@QRKVwr`+$G8wKBWxYsw{nR$Q zR!D5?7lZ9Zr+j*w>u{u0AHV2-zo&fc13;tOeOQwr2WC22(Im!;xiDHVaR?SB$<#P#&n`szAdJj(Wl%^fHOLRC(D3#L-v?$r?>=u49 z|0miD+?A?{)v9}s)ONebkC@o<%%x8b<@rzMK?5u6O>s{9R72?V6KQ{>@=TAK7+IF&AHf?7EKR@WFtk$1Va&nE z=(|1GS=lzgu}NZPWOOPg$DZEazC@Vz^!}C36_GZmKkJ2hdJqXob?^+*X|_%x(+7=! zh9;1a#TQDOX(SYU)5)m)^WEODyr{Jh0zZNrs5&CvPX(n<&7|AYJBta4CfbfW^$&Q> z)VM4kk;PAFLzJh!u{|r!!1o$C1xfn3okLn0f<4f|o?ZjhsU7INMNcoXH*uK9EnlqR^oc*yTzyrA?CgzBY8O)wadaYTI*3d;r@kb@q z#!PG(*4W$Tn6y6QG@DM0o$wMGL9 zQt}*thID2q&N3+EtD^kM#Re^A2Q+~eWeR|&$-qP?0STO^rIr9>OHOj^S_181GKl$_ z>|t4;n{1Asy|y%VtXLpKK?51w-PpJhS3i;rvhnd;o5g!(j+Z3l?$~B^vbP|VvvK|8+~O+`}EO? zBxFUL>Xws=qNC&Vj6;boXNmf@7oQQ>+Rm4Ygo4}#7b<(1*535gaCj?;`|fWG!N6}5 z+C>QoiwRD%Pzl<4Oh1azAl;EiniJEwH`i507V5RKPud))ncM79`pvLAhW;18be{L%%K_P>|X9 zTC>P=C>JIQZ7L^LRaM2r#ubHFuy56)2j=1>Q_=7vuB^FC7~D8H8Uk0*S2WHsY<_AU zymI0+@9{WxZ!iCdojuB7dir}he=FM@effq%c~MP`)TsFM$heV8tyce}uhe-&xVwb~ zdqnt_n2=Cb7zv4>ka!|xN@Nnapt4!Q!`2&>bzQK=X)i0Q)xze~zo@Xh7IFlE=x}ro zmr`b258RT^GO*;AM)vKl+YyH=*7%_=BnkURl5N4p!cH@pfcIgq8Y3Yt#P_*U3Mw8i zQ~zYb+~51+L@jl7`=myzM2UPsmF;iHi4hRfLw!7)!KMe~_SJ0Ffvl}r?i=4L5U8SP z--aT&GDed?Dr+|Vv+3y)`J6k><@V*e0COX#BKORTRP%@XCJmTnne(S6WRj&wZi6N+ zLY<}>MP_^$2cfcEQvqK>-kN{#@9FKW!MzAM!cnYDc^Qukk3)dJ1B%-PW|bm}M>-ik z2Z+tBA-`ywwQB4`&{UpbI#P<8-kICJd`zoUH*+~ODj(tI=_JW)wM@f6k68GvREL)S z>}8BwSpb-++r?6r6xhbUSz=@gnNi?}mLDd25l81N)R@~PL(eEwJJBU)_oh@=pnMuq z0Y4f{A5L1O;_3grYv;W!mBwa1nWm`k+}BhtAt*ggXXt6?%7+WaHcFl^tp!dTQlU&m zOtLmi>3b+UXv)~*A59Vyxvm}mKYBPN(B1Pwza|83Eb5-jo^y`M@TDo_C*&z{j5(|g zW#p8?&66E@#U-LqM}?Kmg7SrF(?3O(&C2QZRCk`eQFrz>DH>eZwFAOqbA}ExY;{x2 zF|L0)b9CE!zT+Y})@JgJ*k+CV^t7=D{Jml0c?PNbi65yzfWHsN*lUjaYUj-HxE;C^ zXo!)w2h;HI%XaHyO%{8hftZ+BTWe3Qe5=DhTSHX}%39?*TIG5p(^@LVD%?Be-1pBI zRDY4)pO-lC$#*gf8{4W!MbG;RmyWx@ey`hk%!dh-{BaNq>7T_P%QQ<jjLADZ4xS;j(?Ve7K_19uadCg5~qk+htFi)f9m0CcU^GK{|Bi1PWIs)Q=l3hVVuWC|nH!w=nZwDj|*jyZwi@;!q3iZ*JcvD-N+>ApzPGFHF@DtfFYFB0gh0Dp)R-SX^6}0daU<&J8rsv62qy z^y6kgDCLO>R@=d2W}EQ%Z3({5R3bZrQO}L5Efh4+4d_nKx_XAY_b9b%fd*_nfxK{< zZj_P0F$`W@bdZt779dq`1KBV#HkGq6m%Xu-4rvr@67*51j8N>6SdP^+S~6ibP`7lgAp=bV7=^{k6afNY%OKx<{n$SAgTOubumTnnb3ehm~6hE%@9O#f4iyWr=Lb01}VZX z`b~9;J(Ko1%9TBVMZRz(u*j*Pwfs5O76O#R@Zam_V#T zdWvJ+N+opP*KD?dIrjAUmt&<@3efwrMC0?6fKHItDCpi*Xp1^>=C$hRM_&{heTHJK*k?S8~DV z=&0d}(m~)Hv(_iEk;DYQ=rzF1*~|smfF~B$yb==KDWH%KDcV zJF3WYbJas!^lKG|v6Z|+Qfy@#VaHH3;Iw{rmGC?2`N=4+WFpY#o{Nx3=Z!Dxs%VxJ z7S~ACo3wHf@I5MmJ~m+NA+sKl)BJzxf1-MG)p;n0(VeT5JWe63^So~>87go%g3y<}kv3~^!gBu-TuM(nD1vtZ z=N>S0MV7j~Xh%mUQY+ACZByWI2HOj<;dd8{I z7pI)@wsv;b4q>ZZ^Im}t&!P&P{s;;PLsEs&gTSpLc!zA5SU|_%&-yy`So_UQCxn`Q zP9}gD&ojL>oC5I*@#Z!_`-zvTe?senhMh#CRCmVSJd5H=7h#4yMDzn_B`7JGSTJ}r zM^fWB{{mwEL$r3ffBuFaB90yq8~u2(8uinvMKbIMAjw6ofQ=^8&e#Dl}56{_HaIDnLijO`*PWIo3SZXyGNx~F5}`tm~w&7@g?=&yDGyNy_*0Zz@`yhvLRPy?;I(Dz0`r%L!aZKofz! zt?>tYsz_+jOzL$=j&+);l?gfap;+t6J$-#dN3CS_)?*D&N5&OKkleFj2|-&MjAkZP zTY^+v;}(;VANGibntC9FFgt<8QAj0KMcM=xY5{$jtFH|Y%^V#@9u)~2rOlfA zJ2`RXwuQ)}g8~o#Oz4)5;eXS^M(4)TSxQ7U8wn+;0(_G0Bkvg&CNIkoD9dumT7T^$ z20Eny8^9hce)aChK{DljTpn*%qCda$h#Qb9oSq605F zYz2gcgN=~S%^^cv7OvLpxzMvJJc2}z;WiMo33GSviwR7yu|s+J{ZcaIq_S!_aeltl z$-!Jas+)YKSdS4X`qWh_E*EL`ByI_uZC9O?_HyC7(TMiTsl6LjN&uIcOqfW$VTnc! z4R))bp4!JTOap|HLbA2a&*xOxW%&d;=ql&bA}p;-sNNPN})whGiqL6-<^?x!l8smzzghKpV=KvfpSC4Ubu*N~d zz=6e}g%5vQPOkp!u$CW|0h?ALbv47H+8{m7uH>-Qx3l?zn*B6&C z(uRN@#R~AcAhSDwMW;Vtv3F?+1U5zOIu$5?@X`WMXbo0Cvdoi-4s1^bJ0>3&>a?Bnk~)?^}YtBF2z7cGt`A>2_&xI5iM(c z>Bh`C;nXi9-NKQy@j{c*kKkjPY8WI17Eh(2la{O~;Yza4cD_%MsE{5L8;dF^mT51& zlxV;i4I^qAMg-jS3@{osbp%4j4|Gb0j>Z5#NZ4g2sajK};tEw~YoSC#@}4 z^02c9utjncN=f5%AfU~|J$!sX?qE?i0IM`C(Q5~*mt~#euoIhW1zb$TUGxt7==2C# zNQTA(dm(jX&sclaKbt;~qU^o1h1i`m7|2tNVyZc9Dn>6cKB5`A2(8MRZ6!@)lCLnR zYnWPB*Q%Vru6t~a+WkRHj$Myh)9k^yF9tU=ivgPP6fV%KH7=H8E+TkQY|qXru_?&Uo%sd=6Bl znXg~3anaNqotn;CX6g7PvS>qws^kRyoAxWVcpWMPe3{KngmB!V_=djq$>YU|DAjU? zE9#6Fx>qmbIq*Q4I9wrvIU=e+OZn7ayeMOg*~*IM5rcHP-^;|c9++UUj|lD7CFCKu z#eU}|nf2Y&VJV4^UBy7_m<~@@(!L0YnAHhI+u&Lk1$Ugl{VQG$7l9F(oC<&?1bDbG z;|=jnM7x43sW;bnp3X{})wvb|=&a19q!4RQN#=Yjw%VdR_G({maFh5H zYxtjK|JH<5;T*(mH?5J|cEjWD>$??~J&hKV zWTTb~aeq6yDI3O2L+@CSHo4tUU%I@@+ShL1)%N;wjq0588MI64b7N*KvHr}fD=m3R zIh6TT)?ZBKeUp6B_=ZnpPw%4s0C?`^!Ym>a{8+siQ{Zsn&b4o|ap zb~bi$ARAJq_KpDYkFU&W7#~_#Yf?#tLhl3c?qrRQ$tlsv0}RE(YNe>xQF(oXNSf1hb1hZ6O&H9)Y+7bXt;T4w71Xgj2=uc$~&Ofo7O-V`mQe+SUD z!YP8=TZ{vJeRf*HS`c}g19jLR0pf+9PyV4Rt}9vis;a&Gj7{hA+Q=TC8ov+$&$_yT z+QKPmPHmeRbQq9s_J6jNqquTJ1ogR$KLf5i}a%2f)Vy4Db;$k;}7hTZc}_ zMqYEjgA>W!6&0Y8)J8;=QJSps&#^W~Ya~cFd6$-@7QiG?E7TIp@@bhah6w=ns$gj) zTLf{0dl{$X!=dc-fjiKT4CBHW~p&i^{n*ds5u^Ya_>6N_oM7$*Ou8=W^~w>y4#Zw>kO7gRGN{O*;+E z6Jg`4RLZqlYAWR!*oQ+yBiC!(mse4jN^8++vI+Ykf>BL=FoDjxT5dK`f9-HVT`=Bn{^0b_UMv6X7gw}mun6Fj}WfgC|k_zAc7|9vlR;ioGg z&i2y-a+LC&tN}$ua+}-+9+N{UKQaY4+3+}E{%S)LGGC*ZTIaIuOP~>ecmEmb zSGl_KH}G#v7?&HeHtB5?YRJ(?@$&3yJsTUeX<4h(vW9MfEvaq%Woh$9$BjQ6NT*EV z(8wooUWaZCH4)lU*9rs-mxgbUj}@8-<|ja!1}r|;gpQwbFtk`*ClGvcELc*SSYY)J z6Zfdw+~$pX zB@uQ19-jk!$wxfl_DQbOU_KFUqui4}3w7sVY_Wf~XGd*i(O+iIl{?>AlZjh8yLf8Q zws`tf5SSCkhwDLM%z?`Zs41^w$_Z8Qf~-iLrnaW4@K)9N!cB&$A0JJ4K5jL!ytV8( zQt^dqux2)|XVc3^@*V1ePWs{DR@qVo9>Kw=kFv(H&lf)rBr<6y1lvY^`g`<&Y{`-z zvVD@zk15hJm|vFjk$D*1ap!jPAKjFdVLZ0d~bdKC?0mQ!B-Pw}3 z(<@E>r`YR+FKNi>H(jkFJVg~P)Ce36wQ`LgLX#oLjik!%Ljc%-a`3Mkjk7Y2=5w&H$2d1!a%`xLLvKJ)MP_ z%3M04`n+AajIpJ$fn8Z8=;Qv?gl7Ydv!r+aTRd0VU&!hzFIr+;!*zoDsycqZ(S3g? zg}e~P-L&8~L|AR>`693fAmjTzH;3>Cn zHM{<9ObW7~;im@8U-N!`vJU=T#qYZ7E7G+g)OsxpKg7)I`Yk_GRk&A4ysK2=HntWc z6`4yqeft4h{s&o?J0GamHyPoTC*^HEj!)8+_(~g#T%9{v_F z7W+6%ZE`x6pJi!yPuFl=axOlVv=bt7#JKEXPIz*tyBbp@=!v_%7DoMpdf?t&ro}rw z)Pas0X!=f3p7DS!rZ)aJnsoUkbyuy(9!`dAQ_7~B+$j;|8Kvb6doq|*t1TyoynCIP z>7OC+oEoT}2QKU%Qiu3NgWE?ec%4Z*?O*Wwh)ZZf|IMWI0`+a5qaU6wg2b|t_loMc;2l;} zfQ@L zaOQtDUoGB=wh_wa$94Sh!|Z*@PT)^|z?P2GDLlEHu+6`6#)3>I^?|nTL$cLcDB{A3 zZLjt5iyILpMIvKMqDk5#kA|#w5$m;#x0`o`SJ72n<+Z*!5ty@=mePbkFyZmJEc3@@ zSk(RG)Q1|!TqtCRrNGplu;TO8?hnif^^MIkH+Tl3?#JvXP^;NetDBoN7ksaNYa^t4 zciZwE936a{5yKOx=V2!=M3 zTD^0E^Rf_)zh8znYh~0zoP-r^aTdS7^cpceN&Q~E6xqshtwc30=VCFC`HRJctkAvS znfgWsj`r!9BUG;|`r`k@`Kn!hNC z%E@aU?989u_IoIO&?dxNa3+&gy@LjGM1g+E2~?%!5yHv)c?AR1g<`NoDvy~nPsG;8;v zG^*M+C;l)@kXH5r<)gn_2i5Sw+)=-{`l><&$m08^MX;jLZ3*}4UD10tt1J|liBa5b z%~f}-wguFnt#`n8vkXYRQb0gBEX&S+Z(LY}I&<;VRB4gtjK2}j_0gxxC>I&}1TXmhQ`88H%~g~@ z%-B&qy{M)yoCt;zz8@>kBfkG*d`T4O&JC^u7H)JA@`AL_IF%nlEA_qUn34|PSrF~# z(HycY-ET{JCCB=2h9f}sM%PHrS^g$<*rC)B{SHei>FK&eT-R)!KV5HYK{MHVVR86W z=u7lYz=`=F8%1nU|C$W!>fZV<++qEAHD*`&G+d!-{B1c%-B`-&!PB(*o5myQPSBdq z9d2Y_e*|<`k%!x{3~oA3_uEPqj2M~)EG_a(vIQ} z-%uO-xWC^Iz3WdLPU-_kxRiG{{%YMN?{Fcubt(?4wRUfO6`kk9oZX**l`N~Z;I7zG z4YYXobjQyL8T8i;@7F9=clEfPdfj+tA$_7eVa(~B!XI5l<$igIhH$b*UoR5T9UXu3 zk)PO+J6q~}TYQAZgfV<0_PNl6uIek=XLtST|5Z21Z^;H7Dtg@Le*7Ml`Bjp0MfLa7 zPZ`y39lj6n?BPvh1sFIf_qjW=v6zhOi29Qwg=NcMzs#dLaPE@WY3V=-*WAN z;pIzgCklst9S$UAQW2tKdL$iklYdfbq1t;mre>O4s?AHrY@AWz(*tZ~qyJ^C+?yJs+DZiHZ+Y{AoCw-ht+Kcg7auN5*`05J z@cHqzDeuE7*63FA%hL$Osh`VAPYOPLkS#No)ZY0dS8?YS*?&2twL=xe-YbQLiRTX4 z?3@?SpR1Rt*EA}7-Cm`7(iHalJ}KA@%=KiA_Dc;7?I#q!DX;%LwAMg5^OS2LfFT|{ zZFqy7uGba2FZMwe?WbX14%C>%ViSGu8$%;c_;0KGEVs(iCRF9^t6ib=B;sNtQ?cD| zV=RZu>~&Hel+Y*iJ$Uu68hX}4y;OBWFmr1^XfFup6C)y`_b8#UmS)EE7QC8IrmsRq zmPErXL|%+zsb7P5e-EItZ;CCKqsmJ>dp35%FX(6SLIo@5T~4LUZ5S@!;gz2joaPcqTE``h|% zy3xN9=Z_V)hmk{A-RZ+q5=F7#?-Vz39Lk;*e{VUySKGvIFkjrl4xh{lRb}mU7002k z-Lg{p#Uv-|VkzBe#}OuF1#kaVeLzlzU4b>3?j#JYMhI9v z<9xllwsWJ0`XM5t=VwM#rx)GE_G0Wg+xsI$>P-$61Mz0VW>UF|$N$>7*BPTmDw<4J zh!sYkc{6NUm%YPKM>LjurLMpOtsYalhtU(Wvd0zIhyex_+X}XHAo}LV_uj9ewPf){ zyi-KBj$y*GZGj*WscW()ro=z2z3+P%ZNlxJ|MeN}?|X6lduha)Y%8ARQO{q^Brb;1 zsY;?D^w8BQ?z8ufPtvZqjn>xOwD$?^dm#U>4OCWpzM4$cyB|+BgY$`@AnmEP*1KP^ zrG8AmJr0nqCl7B@<F2^;n4KboywkSsoYX<=mun%#UZ_v4%na-Qdx}rT3 zK_9E|zN7uGE1m6cqMU?r6>tz4HP_Bz3N_idk-!w4RM@iymhzOV8T&gQ*93NDtn{4P+v%bb$?S58G$1N~IfOe^MkbvoV5kx!Nz zuGzAGu;?b304{&J0|fnTL0S0ME>xmsC%0ONz_)m<%qhV-o2K+=6Nba zjsn-i?B7d2uP7)eD%-k$L`5xWMkVcqxS7sVhb@biWz9=Vvrl3HFnm0In(7~R#iIR% ztv;hhTT}6!YPrrQ(t%q7oe4L_-&;Li5&dXNJKm|p5sf*qAbZ;XSG}o7`_CoOHweID!?UF+dbBG)5F|Cp0)RHH2>|X52bcRR!l-{J@09xm2W2edzcc z(+hCGZX`1s(k*m8Z2??L_4AFH05WcUEL%}@PDbd;R_l6-1)1j|*=|kj3~=|(@!gl- zgaqT%z1giZSGh{r#r<_p9|iG7^Ao?jw_Xod3LP-e3Yd->xb>G-LWuQTHoWYAhco4n_R zn%~X($}CvCNDKTRoa1eRYcN&l>T!t~UGHkebJAz(zxY^>fuBIkTsdOg8bHYK4QA-U z5*vs9li>e1ZA#+E>~}p_c-f?p!$NmkQ&(5j(L+pLp1 zOkdUZ^uUONGdfbC>lSInt2o-9$t7i6Ho%LJ$~1VH;UVzOAHWAZ8Km^=qM7u0uW@CL z#`Nn~3p8?7ZcCCG#PG8$Yd#!u>P(B|^fKfM3hQcVTE1b$?F)E!K9#2LXradeu3_GC zx9iK&RM;t75Lj;7x^3o^e$`3;`N%3$VnD?Xz{A*XVIMniyguF?Qb|MVm`=*Oe)oBY zzR*NB+uxMm+nc(MXsJu>%9c72yAghUhny>CPUve_vAp&EvwwJAf(jfbd4!&XC&-f6 zJ8@Y}jR-q9ymr$uOcZg8`C3$z3{sh~bK+VCepIwQS4BTR>J(jS3J800-BpWrY@pes z_YYTF=oKJOpFWIK?fdK6ji^m1X77(d%_C-Ux{({ev~d2lyy)d2uarT@QeMi% zW`B~YCY&e~qcPsH>_J0KL$hj2Tfcl3yqg@_Txl-H^pKnGryqjfXp_UB_DfJpww8ET z7s9C+Ni7@Lm2Lo;!_8|7R5(N$NFLFq`nxvj!VWLEx~QXvGEQTg&raFFX5^ zwTzELWQVva;0*#B2dicf6V@K;0hN1$j+NKw%4)a8+!Nsy&{rKndLHDpDNiSF!k6(+T)CyKbaKR<&*G6vx`unk zXdyo0R~4{nc|myE&CjciqMU*EO$U{>USG`|J##S5`T>akWUB(bG`#Q~tUDB^XeVNci&!`<_=< zca((>HOB*>bx{KqA*I`p9NL)}>h9+iM4jLl`X{LA7_MLIaWkl~69>GokCt#N3I0IR zsWL_JB%q=aV5Wc%%;Y}I6Z|UrACFhUb^G@d;!}ShnMkYBI$>P9 zJU`hxJEsOHyVFpzEpcVf{aU;~_YM)dY)XgTw!8#c>gh+NX=5fsj?D_Y=aD7q#ld;S54gBH?#BCS^cNNl=Np zKU?J>Erwvrgz@twFHM$6$K`GoE_*T-pM@*iN^!k0q696*u1sEFKf! zG})4R)Z<`cbtB@HNt^Y-z zspebQhdrHF-zDf|gdA@~Ti4J$_KkO3m}#5*^@c-HWB&1_XX+(f4egzZ{IqydPU3f5 z!X3B|*DW)etVkze(*FE^))|4rFf)*9o0}ii^+E}8@w+7&LE9~r<%Z4gdwPh81UATU zb7wb4(#b|M9v#oL5pr$m&!!L;w=1?>3BA&Pz2HgB&(BZF#jj`r1jl#%Ya0-#6P`+^ zrJz+#bI|$e^D?7a{QKTOZ07uOs)l5jOyCxR%?+fj9TY^9ogG9c{Ud&g^r0DgwU0%R zIKzQ6O{^R;M-m_QQ4R2t7mXpBS)Z;z{oE#xr%!w&xpsqK8aXpP7gojZnZy42060EoQ_>&!S!GHe&s+D$fODyv zg{`>85pLDZ@s%NjXMyw8Hp8ADiJ7!x{_jw}kv%^@I6U~_YU%N{_|P~~jydp{8P~Go zhL9oL%P*m%kUX}89#YJs+Am~(YJjD-(!LM89-sfQR)%`WZPwm)mQ5Hat#nxnryYmp zJEoK667X%!vnmaF)K+%jO3Rr#W&pXhb&UKQQ(2O@9^S0+x0Gn6$o=In2B2w;A5OEv zT=M^->MO&dYP+`S9J+??Q0Z)YJ#bH{fa z!VgsD+N;;O&TDNvW6%cu`)StnVKLEZ_!d6uE;r-0Wkn_J!PdK351F`7@l4MqD$$x2 zY#^oq5yW@cyoy)#L|@E-ls4P4=0L0)y_7P?&K_*_FhEF#|LLyV@V1J?j8}~ai932{ zhjKNE<&GmN;NsNEbl)4v3ZvU0z*Q^bYZiaC8n8X0o9TULpNZ4H=%23g5{jY=Vq)@* zkF9Q@b1XbS6Qw)ps}a(>{!f>Ow>ue%hfmP+;#JCQ;|-?B4eYa(DEE&DK;FN~AXn*=zXYJY)06b4fRFt>xI$ zw>QmoL1yOHgz){b!gW8TckJ)qBtF-zzJnt^j|hx{f|iy^-SAjG-=_*SV2-OxAL)Oo zCO_TZ_Pv8?l>v zCo4g3gE4i}a&O048(mn;lv|SpMh6C-{m9cStIz&kS$eSI2;v4e)>triJk%C1dlzov zMM8#OENjFQoctVF>;upzf!VRQ3Qz3WJ7nFjm4szXEpetcx>OU1R8*8C-@gB9-%G#F z&tDRL;T@zx+;TE9ax%ENplK!G+z>tELcUV7x2bUJ9NruFPmO_UT>NwE+)_K`72~x*67wj*G^Q0?|bJ zUV+Vbn4^n}{oYp#U6%)q*S9lI$=19Yvk%AJHRR_P7nN2sdI`FX-=*m~_#SURdOh7? zot58-Ny|Fnv9(qtvE46Ho_e-kQP$lgT&PZ|p7QxVu!ue+MXTtNdoiY^=?dR&v!PRW z$foF-E`AXRytwbuzb6-S+kW@QeXBS=;oIrx6$R3doT?oALE~tVAxiI!!a;rZ;ApRN z(Z$)CxTn*br(ia(6){2=%~ZSQBYK`GdNNT*!KLxHu8jKf5ge-VbXxU4((?2cP^ZoB z+VOy}WA?#Hr2DmvJL;>=>eKD+15GhxBIXr+1oRUNh<>9df$SDH(eER-^b!3>d-xIS zMOkJt;J=U$Y*hpKFS&o5t}7Ir8RI!^zqH)E3~u9@RF6OXcvVch&o6w_U-H9dgl-Ed zQ!xa2vG%Lb40ES*+Va<>^SgeIpxsj%+Xfd*cI1(>6B}%khNytG^`+ph_0luu5(y=m zei1(A)r$x6^GhrPmVJTguHxC+5KT#wihtF~#mOC#IH07i^m*(ESU9oz80~$Ty0!H5 zIPbRHjs<_bt})93X|fL*Hux6dDngdwnMMBxKv*PG0+`DXR6MyVm{jCb4cS{R;m0PbDc3T6J1& zF9fW%4-Z#@pY9mFHn}Lb9;2UL!cabJH+!wNFR|j|O#I^Zy-4&O!Qd;|xbl5+g{`|< z6uMa@YVF`_y=ku0=1i+!yh=U|qroKO?>io)dfP>B_k`rG06_Tj8pDRr&F1xc<{h~N zM&1LX?kbWFYN8qEdYcU$UhBnyo zg+W0k!ZLLGgl2pIOh`Z&BFFJ}DQeOI!iroL#5|e(NVGMAk5*sQ>@y`WQd?b%@8fe{ zo~Ko_PtxBXaLHv=+8XtABK8=@nBjF<)b_(toAzpvv-9Gajeg|NW76Z(5k(L${Fg31-v}PEn9w5rN5Ew{g z+nB>36>u&{0V46{NCxz5BoY~EMEDHOO1+d0Cpx1tNIpf6K5@WdMz@wIU6vuPNWV2X zQGXGxZCKZHXJ=<4=)ww2K`gMs=_STKO~Umu$nAAM9#V*d3xVN5O|a|OR-58x%)9T{qkN8w424lSxb-$uUuds7FT*2h z>G42;2<^eSn&&w^nv^{vcLy)2Q{3D9v&RLLO^1%848>cQb?u4 zMddP_*5@v2@v=?dqYt?r@*6U+sLKRlcot5DfG3 zRZn;nIXNTDHQ-l{iz8q%GFAj6^OCFPZmSwObiZfck z_l@Smpy3vIS6y~C(fvav2 z0A1{TikV`(900H-Q5skizc;-Oe|iArdEB;ZGi&M1Im8ruMk{Nni@PhuSF9p@`}r2Y zWXI>o0-!H$k%NiBLove$nSEcTNe&wwELVi5wWTJs0N%{E*fIQ@mbY8vWy~~*iT{*< z>@8bqQ`1H?!jH2P5Gb|i-5l~T8Vx47U`Mp?J=4b;YtI2HDtt5!^Gi9Oo6ewGVFiXb zp}mt)#nIvXnwnj&V7&0IUNa{U7KVy8uc+JAajY?n>PGlI-(p$9)6Iq5@oIP}J3qhV zdrQ=T#0=kbabXJDG#RIc#^C;flbGc;e`sI^UZ{b2hepe(@5JwE$6<58W12UdTN3L^ z0ut{MYf@rgr2!a)-OrybU*UT`0Kjjg9oc%Wl{t|aF+kgKylM#ax-(}p@_x!fJ87rn z3Zk#fJ2??j#|=j)4gjiN(-Drx+m$V_{Lk)6WUk9>YLdt@FP~Sy@*%5`cRjA!Hgit# zzSlPlQtu`L4Gd>8@vIk};z<*SJHQgmxMtek1VUJ3UAJ-A#F{7q3F9Whv(&IalPZ67 zY$3{wf>}XWF~^*yEArU|F*BS4^QLbkupTkW*rKRp*_e-QtpU*{FvirH|9t7mg!bbl z89Z~hxcu7};pPf!X$S(q%V+R_l5nV}|EI zTica)jjeY;;LM=sz!|VlD0<$uG4t4MZ~6ex+b1ilVNWk7C%kFx8ry~8hKsc`6qkeF z5`fsJrrwMyDrzf+bATkybz}d0@95Z?km~dNRl7Skm%1I$^>|j1>IN z{W^)|zNh6z+DXi~XHHYDinHm6d$0#7W?k>`eIFG@ z*!jt-;JCW|IOwvJWWtRGt*i{X?$r|plcnhP0j$0@VJ*+&=J!=PaCP6Us9O((s=+h3 zdtd_?fUvt%*kPIgiEgFz>Bc>Mt_gW*#NXeZe-J)gl1zHXyRV~Jv5Qins?pL z%3edrcszgDYEoB?H|ZO~L|lz?$zhe;sf&DmRV>Z}z-!=ZA`@8c%%nepvs?YB4N!rkr8WMn-C4`h9A z5tl)qHmfGf?4@WYQVLLm#c%fV>>tt=9=s0j6e{kH`#Q`8x(y%3wf;01m2?2~29Vn;!=D$VFyFL$E#kKKA4u2(6&qSzkVDV+e=K$agDNDaVhwo{+O z)~5h-@w?#C_2u(R?wf)kSVX_$$AWLBh*DtLZed&AYO+~ ztx(Fxm5gJnj9ZPmlJM$;tL7s!U>lU^L&6NxsUALN;4>0@vu2k8j7DPnOs?}7`6}(D z;7z;UNBG|yM0)LC5_nyeC-#|EYW;ZJJZiD)Q**t(`8_~bKkWkHXJ)_+u#xWextPzXuEL2V?qL7uzdg$5M)m{?dnx~E6)r>{Nuv=I*!R4r?Ml7v-6?IJb6fRiK`kyhpX;hD67x5ua;ENlEx zsQTg}(enij%~#j+Hdv(F2Ca&^3rDt%tP3oV<58(_TVl((`*e|R-=lZ1MXI_2jqkgs z`4jI9+IP`hqhhZ=etgx{)#uurtHav!_z)b@V+`z1bZe&`2NFB~+}vAZ6?h(=t&Hkp zy&CrcYMK6m@6(Hqm&gO2$#yLIcZY259%mF~q6WYef$VYUo$bp%?RLc*N4~c-V(zx2 z^;}4VDfcjoZgl-eqHeDSHmlZMVG#m6T5qFUa~gdiPi{~0+^Wd%T_g7_mgw_HFwA)# z$nN())9&{J4?tMa>mzvk!o59+MIU)nmKyBHLp5`b1=6?90$Xoi2whROXF!ONqSneh z#z2n~@U`h@<`H%W#6pzaC0uo)gZ0K?Jq6*}NuZP(%GH&;TE}fSqUEht;{XS;#a1&| ztVM?ftut~4=;2JQvUK553q|qxzP?{~LKor?2r3rd|w(jYO@DCTEDSD~V@f zSDKHw&99M=>{?nV+Orz@VJ*3^2w}N8Ry1Oj2|wM!ZdUWz4}{eR!d)>gwtlV1;>Qv> zc}bi7qOAv<*k57fv$j|bV5K@J=#J?lOApuXH3vt_tvt8r8SqRnL0y3U>7v*9Gia)(mKXtDdX6Ci`P%9RK4CfZ%`K;iB*2f)1Q}+a7LWieThc@c}e?{Ql!huGpc;+_&p}Ykr7=Q?Y9pB z)c`lp$h}1u$8W7+Qa$0ckdMvufM0J}`Cm-`D_N zZe>|gJUIv#`^xX{Dy_bNe$}Dnx@&~P{4mfQJ*0PX3k=1OHLuvRXN+#G!aF7=d4DqH zdr#kb*Tw=Q(Kc|vp5WkjbqP;no}|=7%3Il%HcI?m%7was;EX?V3~}@+7eLX*zF3}N zK_~aL%-$T3ol`*pAb#Ea;F+P3SI6yFFJ62Y*VOGU2(&5EtU)N&!I&8^j_Py!` z5hSE}JI7)1yhQ-GfVoOO6ZAuzIP+`BFeps;f~ggyM%(`@UcH%i#; z_usm;51So0W`=F3zdl91HQD`VAgNJp&)<1VI<0eP8q$jZ@E=7z=BrcrMcOXCd&;KA z=fyfHz0Z_<9u}R8v_}a+dpt-pJe{Wj;nWu8aRWE^UTZFoC*_I6A0od5;w>~=f2S|E z{+kQ%+b2Xwoejm~g!H@m$6@oM`t!ezOqEa#) zPGq_o`<3?qFni{lV|MyTidHJGF24YlV8YGak4SpeQk}ZHW9(*f9??tlv=AX;JYu04 zZ?|BA3J2$xC7HSt`R$qf4FD%9Un5>IVb^#3hm&=MUyeT|Z)qn~M z7zopmIR-4lFum_)VhNkj`Pf%)1CcYN=$I{q0SNTMkEg5@3w3c3a`4U=@>4C+Isqj5C-$I@tMjs#eo3GNSj>^9ka z>ilP}oR>|VH1{SZ#H5efuz|V=%8xmHRXz>XW@o5NS#*#Xv@2vxJDYQ@!V}wyeQ)l* zJGJmkec!B^s<4>mHshO7)K!<`-$yErI)xASMo-_08`|97Ctkj2?r{e?YD_Y*z$15q zHZbyD>kIbponJgBdFb$z%HHsgFYrOu>fBm-iV_4{j(3Dmg1?Ms8iTqy_ygYzUq&Qh zp`l4G%Kj(Pc`Dnyeetvr=lU1PVQk_fFe)Ejnz9RsX*=^P#}r2D;m0SUuX7rLJJfEB zSsCN@eT16NHEc2Iu_8|cYkJ}}Tq#zo7kbKC-o591W9jf!l165h6DAbRX`kbk>j zP>{+pxaep@fqOA`yW)VIJ!sV=BJ29vI#8t<{<;MV9EOJja0IAlL>NKr#_*u;gM>0P zoLc`q;#UsrNJyRe0?jl_@^D<~q1oCVvVda+DP^$N6h)6FN#QF^j@G1)2_rvqvk;7_ z030cUqUqanZw<`+$Hn-=j<(vAubmCtzWcANa2?id6=lF4Q?~~CcUZ%>oh>#&4II&q zy8$vwxc!0wgTEaMBf#>#0I&&)1MmSEc0I{|?UWn1(^3_JwNMq0wOAG3;*SHc?uq5i zLxXfb^~*A`$ww{l=`+QX8cR#k{;Blg;A6=c0}<9|kZQuCB4Q+$aa{PNt6wkQ;}37$ zB|OGj8;&~B5ULwcIez;OqehXCP;D^?lfzX|JIFLOLX-c>cw?r z68O5Pc4u<39{>A=`&fIF8Ry=Orb=`0_xs*;z9F7E{0M*G+CvAQLHYSPmXUY3gKij} zLp3e#f1eY_9eLPVYaOD~QAhNUtJn*a^%ZU=74?;v4h)$xc7AT$Ql>lCnBkv!-vQ1> zXwQz%XtYL4B)MLY_3w2SldpB%_%2lIj*D(;kK=aCFkfP5lOp2eB#Gw-fsh^YS&&rN zo-8cf=mzlx2X_5${zOmMzv;j<8t6S7H-v9vhTP2&5r^qicfG9MLv(?tfn7x_IK>5V z(2alXkPu`z(~!(jueIq#2jgMJ6LGn z1Uy(ML03~IuKeE30;m4B#oq;2NJwu^FV-7gq$2vXzDO(q-k>reVt;=LpwG`#WOoI+ z*x?E9>z3eZz&BpJ7#}r`E&PXI1jN%m11d5{2VJ5f`ftM#ttLPCagrcB{FAEj_}ZB6 z0vRPO)J4@`_@8gzXBqO)aYgaf)bYs%r6e`(n-iZj4kkew^LdNF84_FI8xH|Pax zLv&F8jX@!Dxajc&M6fXzUOf|@OKvp=#s8{T3IU@0X<1BAy$=lR>2@Mi!Rg?^&K)moBo*@Ce4pugg6j8 zJfXP+5AUqD0SH>ZAwimkbL0P043dPi7Vgq*4j1t)(z`EP7<9$}z!8_YJ=k6nxFgTg zPHP1a2!ZXlJ)3uULpH_qWaIa6v4u&0SA2k7yf*>?zZ)kSpv!NW98pb2HJjxZzFZq0 zWM`){<^Z@DhH~~LD`WU+dB_~y%XNk&X%k=8@^zRTc_uPo{_%*oPB>t^Die<9w_-9v z^cQnR%z!f*zYhKN%FT{~+ z(3rRD1^>CJW`g_7TpYCM00+m31f*^s4s5|E0BD_(ntCUs3y}fk1&LL^R&^PM@t1|? zYk1k1ZP*wFoQrjDjUJ2Ax=Z7t&y(!pCgg zYkWXIawR)#J<#s&MtVsKO%UnfcPT(-k0thoSf@gMTUv$#!)O|@;Fdw>&> z=pMcUn#42o(xnO`-eTu(VB^QG%r|9mFcA*dvj?y0Yz;jPUEe&7qC69Wyhfl7WVZS| z(Qe$FD^7Tl>;2jPiDtOO#?sx{06+Z;2j;sEm&bpmn{VJ+sVO2)tz1iKh@-bMJQ*|6 zo(O_XXok&2%Yv{L>hNbU`uzy6cbw*Deb4Eh+ZzFZ&5Z?+rf~k5MAOhXY5~+N86}#q zqmAoDyiyK+&ai4iV*?*g_*S1I?Xa(?5vVe5L}-{1uxsD%M_5BOBht9GMuV~e*0{|9G{ctu-t_&~BeBPqLYOYg9|86zSe6|HmOTo6S~)dhLR-IYRZE^Z zWnK>YWO!5pO=-C0_w&tmcFp`*RaM7j%@5+8Ez68^J@l;QfUjw`HtyhMkef58YZU6z zmC01Kkk$PqD}2@Bnd# zT(JAezD@_UNA8~~0wopEfTPYi_|fKvEsjDB`M+*co#wA!#;#6Anm~|m z4DNrFEISG;I|ytOQiPOI+0p&nT9Z;{;5-eZPI%F_VZXf3B$?mJNAtxSn{XRZfzNz) z9u+1*O^lF?2O*9-9vb)bk=Bu9pw`PF!Gxfk^z2OpwNDI%2GP(!EHeN92VOa= z|IU$1`IYmKmbMg|<`=@#p-6Po-G-aBG@o0&P{4pv7Yv!b0pq$v?>K~8>G?uY_N}AgKO?L#nFA833xzlT6A~QqtgBVxssjyK-MMu%Oq%Php4QB!d z#SOxt?qos({bK^-yVCT^sUqIE=2_VeEBnMu-(+Bz!9nFNV-#R!C>56ohHUE{39$PP zQPBAyC`myqm@z#S_Nk4^il}sI#h!nAoEjygRT#(DS}d|N!i$Ljttepq&$>T1l9nP{E9>!%8F$OR045z)|DNC_Gs$0)c~NVx)p_L*U^5af&K5 znV+~bB|1F`k@IE7dmlo&jE>!enefr9hz|VKJ)h!MkCykIhI$gwMI}pH9yr{)t>w}= z&=*Bp)L9Mp+E-xSv>aZqZiMpVIT76rcTv-}fIs)&7LlN3m@-NBd)8K?lv#q1TKI6N*X67j$T7f=+DqHJ9of##3sp&SP+DA}pGB4!Yt@*2XIdV=sjPFm0 z2f-=b6P5DeNOpE^p3fX-9`ZZLmm)g+)>dEx9ukxL`aeEu-QW2hkKJJ$fsTO=h{xWu zWiEJ*PL9;rC{(4yr@5l<5ly+z<bdKskKHFT~-LRUiw4$uBS&XU}=PY&yh1dYLzU){J=)L*& z@>$P4IXhe{tE-<5vT(#vEMX9lAXQ4t1LDjHKk9Puf9)jIeda;pD0fxVR0aJ~MM{!G z`Xz@{<|oIBtVt*?G<6*dCrT-v2@@3+W&gSCT}JxCXsrg{`QaD_u&3GH*#RkWp!$>m z_x~J%0v~W1cq9=BYyd?^mYrBnJ=a#b>6-fff;SB3FW@gVMD#?<(|=>h{G}f?TBb)vVNe>>wtk(uO+G@%P8&=FPy%>*NO-~5e^3TDA#DMMg;g! zsZt7E_Rq%>V9pyYSuW$2wvsyu7UFmGhJA^G<&P z=lx0Ii3|_Ixb)P}7njCsbQd9HR7gb%mQeAmkuP-t<+{QxAi0bTyhu zh+G~$FJ;N{cH>{XxyE}A60vCwnvMLxlO_M9G+1ISf!UfnDoip_|NTE+Wz6$MTXB8s zy?w9Rrqhtip6t1EMMWv_dZNW!7e$gUnjqNYUkeHgkEh>d0GXr{uGY9DJFDpra8L+$ z!1%bb@I{8!@x@uSi&6+;%fsrOnMg}YBl4#36%FuZRGA(;sa0k2t2!LW!a1RUmrK7= z6MEO)0%a^STXV_DHBA;aV@w?I_hSRxTv1-CYwZg>X1ol&WA z?rxh#2ku+uO}PxnP8?-GMyabYTQs(~H5!y%UeGmM`4>VkROyL>V4y;Key^oA;rEXQ z`u;3;)`gkst&#r0w&ol+liZ(1gAm5$)!pg+4H`&QQ*KF$R)QL3+^*Tch(_UMQ}WfC z*`U1jQWIXLVdl2j54-SqKshMXn?OR3QGfYDfM8(8y8BUrQSQ?$5gH=qKDX-pG~yZ zv=G~S6He6UisyW90bZCwK0*$~@*%n54Vq$Pvo-316y-;Y7&z@3vg9q!OF?!fu&wQ( z0Wtl{{(-+t?bB{UFmy#zRZL|;=jnz!5jhyaczm*_{4|5-|Kd4s7?5GKi37#`(GyG8 z3MqZwNtxA*mH9ze+S=PG4&dO~9cQT`z=9}`EsOT9u7Q2=Ga=WffJtB~~Ci4#eTQ5AkWHFaHLYQ))C&&uYZfAG8Lz_`lr>ToF(OY!2Ltj5oo z1&*_xjCr7AaTwDJR^N{F$AwPZPcm}ywiWvr>oe1Vihbx%FUefil z;nB8MkxVHI{1|r8ni^L*}6yu;&+9m$O!O22aUvczWo&rz^&5AYB;4SjrQ zNQQ4)cn>4yDum!6*f!sV$$P0Z`Q!JBB76Yc$?4Ax7;Cn|A0MwQv)=GX74StQ z_@;(bt6yn}?0AY+wmosRvb*{x#}p8)RYhRgvQIs@mP;lkM)!;74FMC;`}T@_%WLyJ zlB7=_#RVRv6(sW(c7@t`_4*5sI;_ZB7XQ-F8uB2zb*@_EjI`mo zy0Rzy;Tb}T$BilSg|vwZeTRG5MiND3t-CHBrv)h-Uwr1mF&wD8xr+UMtyv7*72 z_9;N^%kR6%4P&tWz1-gE%A${Ecdo^hR?vC(i>-*KRyA2UUkUAjUcoeHW*WKRXOwrr zAyL>QV3r@3K31zIZYUr$sh)hMx`ui_t0YuvmVjpygZ-%-y7Z(M;GE)0f`Ja?h~xcz z%kP(+ZYT&t^LUdVm?ZOh?eDLL%A0Xz1Muqe$y%j zw}x+q`aX9AeU%~p&_%GSssoGQ#maDw(K(n&U52O0tMS3f$)Wt9EvZWM?rOj7;#H!d zxm~mmJW|JE`y0Cy=-rhOH2E8h-=TCy)sB7VVHFL#kP**Att>3u1H1oEkS-~SG! zoC3(tIW3XG^|#I4cM3R_*0A?mDbNp#AWeWtgJ5 zI(Xo95WuzTnfb%x(23>Kx@*UF9e%-GUw>K%_Qz?mIEoZm1`VTu8`V_VUSueV`={5H zSC$Lk32&P<)a)ixb`I>sXJb@U{f}zX-y!>Ad9fR_H!WC~BDb;#BLbC-XbtD))3-^q zA`uP0m*wJ&_JQh}ZJ&Y=i=?CrZzlaVYy9R61LR6NOTxAI?O8}mBcnTeDSTKQu?7tf zMpVXm=jP@mUdAq;2A+9f{DH9-yoGp>IxU2TcdfwRC3CZvsXBc#U5oOzzf#4Z)zQ-n znp|(xJefJVz8n})RMYZDjm!IFbF{h|W^)&vzZBj{L&wOldRHpi!?xrbjv;h4HX=w} zO!k0)XSC)*$^WHQ!-gG9$S)wcyzw;HVJF)nsoI0dLPBWqiHIyjLCk~nY^%la_yt^& zT-3r{^lHXb3Kee36MZC5V)XrPJ;sj@Ei-_srONke@ZG}aUWrcqsd-#1+ziIJI+Z!T zv_r;;D|)aH1dNprGuU{l%n$K+=0xY-UAUHk*-u^b$E~dEcRmZATc{==qnUXR!+-|t zpsU1w@O=d%tgK6Sp}3j&Z+Bde>~jLO0lJ9c z>ktfCX_@vB-y%sZ_rOI#B6G&3+j|u^mrK=@ooX@TT}em{diNhh{j8!UWxEH!C`U!< zzzV{=-Mbj}KtnKow5nx6tVUjD|?fvy1Ivvck*~n4W6vlJzD?) zDTCUVVxWD>^P3>X4X{v5*R%C8?&Bz`;SeUNCOqsHf5As<9oYUt)9clpbY8JqSn9}j zrf*=;PaxhRtQ;s6W@`%RAsvjiH3FQTW0VF$)>&twgrk9?0h|Lc|A#rO}Js;|pd)pUbVHch#&xW{mrPm`nGE|XN2BSD+ z!*1OxalMoBL|vsDvv?cU|C0IfhK=s0Vl>d~a&%SDo{$*ACKmw?`cegoq<+-YULdR2PUI4b(6uv0%6leFq;=H5D_S>wynB?IpnIdx|PIH>(N zHk&%J?>Pw+JDY!?=vfX9_J>ZS&lq1_7HeM4kAOuTK|T-W^a+pEa4kMQ*V_wxv3guM z$BY?l9miw9>IAftnSN(5?2*rHTa*2w`} zQI>FR@Rx<~Q~%zz`2j=IUAvdHPNj^U1>Il5)69~sJ%sT~En+U-kO_Ko+pKz#@qJID z++j#&f2k53k5PUsdC3oZTo9;!LokfMgef&gT|@Jz9(xFIqUp&T#1rXm_+IHYAIx}7 z4D_4sHp9y*C!VqtRdv4js@q69SNEdP(?VjVX`9R7e%%mAkwUz54o)f-pb>tMeFnnI@C(s30-CmJ>h4Cq>@=&}BQVYlAA;e&?ctQ8>Q{EKMo9 zTq!b3Qt6H_TXB=aw9UciTf(63?AJ_q`&yA*P|CR@X}iHNR5>m#CM7L$CA)k2q38{d zHrBaw%UM{6rr{iDrR9gR@M?27*Tyc zV(LcWAAfTJoYLFZ8O_@!CeT;Nv)OGn$;z0+iw5OjUi;{=exMNg@ofyrTL-FryaO$)a>{YaUi&hYyn>O!sALf`=Q4?Wv1-&f)Ut zq~}+q^EElj5er+Z95$LWX3cy+_sN2|!HKWd&$A0{fceoJ4ZkUm7LZ+bcy|!-=8@lR zO>{bAX!`f`=woD(N^WME;ZC}c=GkKzLklTnHUSW_!PKc~enAnWG8}z4H6p06kksSi zAea{U@>lJEwCr0oQ+gU2S{za*i9N8t{~Kw!(WAP&ou4yHa4_p;=CoY2$Xd99DfR{Qi zQ>_~>o;{=Mqiw~QThf7w#CmU1iP&kzSxZa#b(V^60^FyaJNmlGx3=(0GpKSbEieo^`2|0 zm?y~^MM?-4qk=(i8P4*Ka8gD_A~FnrlP_D;G;fI&3J6qkC0uLUZLrY4QAbV+|BlhT z3LWFEVxx<+e0||!t_!ZItE)n>x4W0<{=xo`sGf1Z(XYvM6PVXMA9Slq{RiF#A4h2q z2)Z6bQA-3H-{M6Z^(0^beb;#ZUtSKhQSYKM-kc|)d+aqe3m?zDvxD}`Pqd}i^erq9 z0JRQ$?I9fv?W=cIy8X?cf%hp~Hwfl-)YuX99Dqz91S=qG)_oRQf zzI0Du)dB?>mRVnTRAHeb!{{_RqMCn5SF~H(ED?MsK<{UMrkSq=Hy9Wi z%^J8p%}zE+Edkl2{B4&STAHAu+L1G=V}YxfCoGoU@O^{a>%1|2F36OJW8o&xn5f~yXRWFNFFdD(T&B`x^9pHmSIo_*Ac3C+&;DF%qV{=HA%Q*y=nwO4sh4n+KXld=A2`D+`{T0FN{G3*%YUI`S zEDpc-Bj<ct5it=79xXzwX*U99K))^jAAZiWHbhzJY+FT;L5 z7=u563brjk;msA^W=#tJmVJ#1o9YE1LT5sigejo<3 zbERDFv?q0p2zPNJFG2y#Bs*P*$ka0PG*u&WI^A?y>?zV3T%e7VY@_pf z42gy_H7vVVGE$+bgL0CTVsKbk3K1k{((q5RKy-cwAgR12SC6zvi3%BI9xFMm-AWfzUH5%* zve9Bsg{JdcU?t=jDmGf6$Gj{(?)}3Z+wK*BMzyz7g9VN7_1rEn+&ny{JVnJr4zht6 z6{!Oo3!X+v&n`>!_9#Uhqc9w1p7T{3rI;DQ%w)~4W53ga(QHY;`=bgHyOD2cmctP(9*R;nzS815C<5-Q`-#Ah}~z^?g#5XO@6$b#fz)ne1-jcZl(3eH^N-c zjo9+nud>=&3DvC`Q_B}I zjgq%OBKz`1HIAXt({1_gr!UnjF8B@8pWEO$)JsfEFppX4w1Aw*b1d%#Uf&J{z6!Sv zcey^dqEg#nIkQl8O6BC3QZXv{3O|*k3DN*1EP>4AIfDZCy~S$MS>ne!0COKF0o!5= z62|${@^PNm5Du(gdz{g$%9up%dVe}qB)$m5m}CG92@1kEQ-7hfIzaBK#G_vk=|q1 ze71;=_uSDQ7}0Nt($IG+m>M1fAlRYI7Nku1JUoY0GbDiZB+|a5N7Ipc`Nk)y^OIBmb`bFI z0DKe!fTOTUsWh0dNfUq6{(&xFEHr-REPJ=NzPA>6T!!7;_T$(G2Y{bO1zvUtA_9$j zimGpb;+rItyONyb$-An>#ll^3o{>ye|C6%J%_byh5JM{w@R+2#1+wr8mavLUnyH~| zu(L)7g80tPReH0d5l;P+EE6a%{u=Dz^%d`bN3TNn_J z6|zYnpFK;pNqEbW2js9w^X0>^$6cn**42ir0u=OiFwSzDi`@+ah93bl*;P~J!vj8{ zlN%@-jNp|gxGoX|1O#d5_(#!xTI!|I(4ND=Cz!^j#UUr@nEh175f8!mBpDDR5BWCATx0fB=i_JzPDCdT3U$lGCzT=fI{6} z&Ww&3Jdw49e_Rj7-pLbeRi}-<5n-z?f_0)vbp-~k9ll0BHryo z1#eAM>Y))5XD*n}=ng^Ag^JleMXwZw3UBw!rn-06EX8gRb!1tCGz&%rKNxStk72l@ z0_jqGSK>K8yk?HwW^r6Ux!4+z!SlhFtC= zzHoNtthXy3sXQze5(>|~j#P%kn3+X35X0nRfh?xiT5o#@LVlhyq^NW&&i+LtP^KjL z8iGB(dhM0|*HEKV^GK!HpUz&3d=iv~3=k^zoLnHl!`t6FO#FiKn97P)s#38azqR&U7KsXOoc=n-j(7Fr~ zQ5>4XjV-M5X@46#35HO2_X8jMIz;OXsVvANV>e?aHIsGssQHtybw0hSS({4Jbc9e( zAcQFNW#d@PiTKbgFprUo)1m6#fdFDv%aX|w(tmx>dLiQeQ|0K>^LPEd1ARV7jOCq` zb>R(u;#>yC?Nz&4#YE9v?s}aB%{E5)4?c@BIKV4%4zixjm_AmTI##+^H^NLwRi~gf zf^9iKLPQ1#*M7=Ghi=w^CF^j&lyQPC(1R^SC%-Czf9C&DK zoxMJ5a#pJ+&R~h`_|g;K@!kUtv*IkjDg#Y`tuD3)$OGabELpa&kXgU7Q5TPamxTpN zEVx>k+(V^5%B1a*T1)vL;y^hofkG|M*j$E7S=t&Q!J#Du{bB~hoxO_!rxHRGQj)w& zz5K`7fupwCPaJjD&Uj=g*rz{~nY8X*xRGTsO|r_wbCoiZiGs8R`^t6<18k+O0cZ65 z8~_|k$&(og2A)*~gKtc5w(p4hwC>r$%HRGKOqzs6&J)yB)w3!p4tQb!9>Mzh<{k^c z+VS&Kz!Jd`*DjUq3)E~nV|Xdasag6)nva=%tuH7Sg_OA)jyd}_AlcVyxJQK$+PKST zulY86L>$HaST%&;do4Z2%*0DI^z)9ekP405b=Zs(TJgp$q+6_!y9^vS6o zvFxgOQ8nj%g}G>?yGu*g=HaHAV01?-cr(AiLJKZ_ixg=7vmau;e1@N4(`cX<2``9| z${kRj4-ytB3rwkJv>EWxo{>K8DjXmINjUEcK9s$2^?fL7-+tUx%MHe8*y7o! z?CNOL&_E_db+poV(nL+|LMCxweNHa3B!3;rM|AQ3G4+)}akNdei@R%p-~mE#_r)P3 zSa5dyxnroW@wy3lorB}&SHV4Fx@rjSDratOp6JpBET?7q4e*}ZFTXhuxc8n8@z8G)X=h!pBeC=_b#Z3O{&+7|4lM6#?jyXtp+@@(ojyi*clC|`sLWfzC(Mli9OE=|l!H^5*&~)UnuqHZp8@Koujh2^- zC{P3zrwsW@8T?J;5?@e(hXkk<01}Jt(bd((Jc=NoJxA0kK)9oS9m?D8;#dO6L#`c? zOy0`Gx-Vl4c8z7P{#iZE9~;tt71y^o8p8?*E|)1#0vAm(1pQcHvd?+(*E~?+ODG!O zW4e1kDhJ0qEt{v>nmfXOzcOprp8#v?T_u+I@kvFVeunEo>^XKvUYGOx+X;;Cf@cS7 z4V(Ts<;=CIOV*RZ%K)Jn3J(LqpNPl^g>UL%7u9SmMC~Z?2=T%lq0I#ZEl*GDho|TO zt$sp@bs_wpcLVC1)W@FGitE1ZPhpuSq6g$Y<22&JO zUxWNX?)wPwwI05JyGs4?*-JDkvHDau{K!MY#u&b%t@;S2UEiUOk{&xU;!gMvq^1-- z_=^sJyO4l`8<1;82-b#j#V~V1y!4NZggHJ5Ucdb4=J5kizy$~Rt22m6n1+jA0K@-pPktlRpSXFaENM^Gr_ zi;P0X^?8BAoY7EfF@Rg^oGhsWUwCBN%A(B7;Md0$(iM;vKZCo zVs29AVc`Fhsf{ZAJBlFn5V#)+N;b9d*&#rDM@32Fv10L$ zZ&i3sgFzZjou5ybyO|`6|0e=?TW#5rX$%w&qUY$)?D67H#Kc@F9K-3Il~DM;btwS_ zoWtK`pNroea@{Q|=#+afCeWm4qhILL(=&)ajij$%5?-C+gq+!dkx{}#op&w!g?5T-x3cdEVGNDytVbw?U5iEr1eYP^wVe*Nm6!mpk#W zb9;W%GarXBl`IZeU)BP7yoxds@QO+DKec6_4FcnyXZX_yxKb$RD^4fuGpY+S;OU|z zX#*?JxYZYiY*MxH0Zd(>0bUy{FSVSSvs#}+!&K&CiU3Q5J@=rT|-2^sR_ghAg z*Wc)6Z3^aQ2FO*GN`Ahg4HPLcVn_F)cm7icG|yBREpA5zyXWaJ&xRCQtq`Xp0={ML*^0HohjfZt{aLf{Yk9M3H2iCb z9&yQ#%5|e~l9g(z^pe^)<)B|zPEPyl2w-qpOOkp>_Xc@OAlcK?@(*k>3`OU}+DLKf zbjde6qY+@h9UINauh%Y8HoT1S=CPwDk})|VOxy3;Ia04u1#hq0H>L>KlTdbdmnv7! zmQ`0{6LZ;i#;i1#=_GI&UDloOc;A%PMjA}rycY;!-y79xCgj@E)ioL7LQEy(+CS0L zn+E~j%~3$;PYIuPmC`a?XyTksU}xVed>1TLw3?{K&jk}p#*0gbD$hsNKLvT3&2-jX zZ94pR_g#&q;IRoY1iR~tUQ=*v{)rYBCDTp*>O~K~{d|i7LJXN8YF^H@6VLak zZD=gNMZU3NgH>f)h1=M727$9LyFq9VnFNdSk{o9XhVW`qQ1H%0o)1I1F2u6L+r@{D zZO0iJJCxSx;tZk|hLq6I0+@vR1}B?8xX1;T$wo(A8i)xHB#ZvK*due)=6je%cQ}uuuEkLOzGHns-OJKd@txO4_oN_Wm%9Dd?ixojK^J)5=bKv*jUL`9Om5rUs?I(+S$SNaiA6?W zc9Qd#uRxxpA1E6BskK_lzvjVNd2)VwQ2AtcHU9E;8=XHTQ|&&el$n$yGk1I1wgpf< z-fk`*#H(Li6S!^lzGf9yS4#|;q8-2)!T`Dj8CAzrmt0>RZwrI@j;-vQ{%gSWU({A-7f}jb-}8@7F;SJGgNq@8k2h2-9b}+N$hyd< zk(0m-v};%u;b)Kfkd?vTIe2GpqMM3N z@bhP}8OZM*DdJM2=(cj&fimwAqlghEs_&jMk&%k3-vHH{589{(d7SjwZaUekP@Q=;Jv9~gBP9w0td3ZvJ}LTv`zuZ2#_>TUAg~V;vX``d4vWK}qNbkj z$Z!Vc+(1=H2a)+|2f3UCq?Hs}X9#ylNr!P?RM${og_r4&h%QpUVPr+YX6LRiuc>gP zYOnnqpJ)j(eJ|M!4I%T>@$d{oK=B?rlkow|j9GW)6LIWNFHUT9=e#1|N4jR2KXBr? zVq>2@)r@5+8B?Q^3PFdku0|gDC}J_`GzL^(Tu55yD$xCKyJfn#xIALi)6jTV-rtk; z_wQfDrRie)aPs&;sKOA#pF=wy{Y_ri^w`+(z@Lb`TNbSiZPz3vg3mKj@>em$zBaC* z>8PnVbN=~O)YM|{dOEG8tMsZj+?ZTTffj8)Q6!%%JmXsq${ki-5BE^*(SHGLBOOQ#=D(c@HE==NkHKF zNwQv+)UC~-wN1}*51H?4^bsrfOf+FUS!S60t~V-w_V~87li=$=OX;uQqLqY^`(h9ZiQ2##cf9DNyu~l>o*Uq? z&6WDqX}*w;x80aZr}ag1oYu1>QG{H$K*4~x-b!U{tiWunOUiLg$=2+jVEvUY*RJkg zm)jxn5dix&4{ujy-%y(Z`K=i4LBbO1l+;a+BMvDLH1Hs>nS(GKF_!kWs#F!c3IW~p z9S)>X6*cyZWJWRn(*jg+SGnwf!qaJumxs#Vg3`?m+aq z`e~V@z+R9^6^F1zByw`}BIRw4zUni5nFQ)(Df+Ir2GObKjA8D^s1GlFm0; zvy*yyVe5J}m)lHIV@IA%ZC2QAU6_RR6rb zTu)YUd|sd`YbqYg^OWfoRW&1SPL^(#6~Dp3NCJ6G6T0%;8$#}@bH0wMsuXFKD`B=` z0q9;M0N%iQ@*5mzb+4;mZWF|Q45`_!>~mKChS7cI5N#qLA*4Syb$s!&F1NacB*y|P zhmT7e0_ZHt(p|HqV$0pkh4osmb0smvWc~>Pi&@PX*BXt;&`J4XT9&aNy~ZoA*)^Xd(!p47W!+l~qv7;BFuYXcVY1S04!#>c{dPV@4&V!^8GTkepqxw+=f zBa5;I5_IT5L3@ZU)Z!<~jx8|Z8UoVykF&N0)Io&38+K=Fa~a(LC4hD#Fz|1%H-Oo< zque``qUip^6cJF0X3}l+Z@eVfxZr#azvTfw>iPL>m6-W005R#zLQ-;aOhPZ)>@{@@mF_6O=3?3?GJgE@ z+48;+l}}ih>%h=bPaQ#D=x&x2ep^y?{P|iFz=Br8UDrHtJTXXmI=iL5uJ---u;vqe z9vcPBZwfmh=GI@HXDzN~zQ^*sA?wHq&fHiI-hL5R5jzyziU)?(kb+1A z?V;W8;nb_|h#6ilU9V1Oa6ZkIsvw{Op~&d#1DJKI$>n%8P|Mz4z4giVc)10ODg>?f zK{g%etL`lIv^i+C8g4Z|ktxZmEEGY^=SED$=Q2MYBU)U$sO(f8MR&Q|>^;{s@XtMF z`}LuJ2FEY0|4{JH-XRp za(bdw1>i(huWiDohcOw3XG=J*=chBEtV#KtaWnRu7)em++Rqi`X+T^Eyg95#s*BDZvu-iS~h!a2x3A_b!Q3zGfhl}jp!Q!=n z*xcUMRw#3uPR_O270--|_ag?&W5!FhG3)5Bh`!5;mKfhzo33WE;r>3(lB6Iyk_X=t(Z*z|+TytK zlM>I`_E)sO!03VX5Q9ZY1U-;Z@EHP>X?lk>lnl(wLhmozdJdHKju?&HHF(Q)qdWH} zy4MePBQjc>HpH(q%B-368e^7QnhJWH#>hyq;F+1_d3bqq%qnau>uaX?<;CW9_V@k7 z5MoOLA@k|=SU8Tv{V|!!WLt-|gvQ3k-TnO~tCkihUS8Uu5DAU&jRG7bilkh`7))XU z5?sH`_Gi?Jwi?i!?IBnuBk^~nd!}!wmMix8aA^@D1`5<%2aDuLUREXIr#ai+IvoTB zMGX_Xbh-E4=e@L$Y$ap2$ixyxKGzM(h%YiM=d3D$V*0|MCfB2gt%-@dtF2gly{UAT zPyEEqwNJa5@xRN z7aq25A8tmZjtNBeG!O3M;sJ^ntI21Uo`hE%fEJu}=H=zx$XxSPOTLX()9Wl^H?!yF zh1218cOxW{1+kX@I5moq5&<3ZYbBzc`qgF zY=y2rP>NoEzRxVa)d5s}Dd%@?B+K>0wk?-!9`2v*v63p5{s?8TdbNSrcLf3mc6O7W4u1m1ozkM;F8EAf;W7!8DoWR1ZT8_EoRZdmoKcJJ0aUaEzG zFyE1RTpyTi{0qrlE!HT(|Mf^*7c_#WJi(o8VTu_mCgzt-PG!_+EpIK&6TY+3E8x#rw zQ(qcqI;&R?X6{~;kUKiVkl`K63|Dt3S|4*egP4~Wc9T;$TT|xlJ=D6*H+nYq`xIWs zh}F7$ZM9dQ)+(PBRp3TavC)&%Z((EN;)W$`bAyOk6r&%ervmjwOEtMz<`)^Vc7a}Qzj%NNJR8ecHbt23Ub zWQL1ZLK9ESW=C$*zanx~H05UX!~+r*HN++i5ouptY<0>=YBaXQ5f{xnx^X+6ipgIEvgfdN53J!6sJ28}G$<(8I`bcYH?K|Mcg94ypKFQr#U z7j15Cb+Vv7+|KwIFHB58VQp+k7Zs>^dGkrQD08>L2rFb2W3e$aWB6ITAS#`PQsh5n zlJNR0mmVFi)<&wjiv=t}fi5g}u~~Nhcd!C%PFn3LSS#Ft3>=Yo`S*LwnNb}73?@5= z%0Sh?pARX{kHW3N=eK=Tl{kp&M;lRv3Sb_zo1FZclMHd_n%b^U0%_!(;I|S2f|=uJ`-(?{uszpudOKo>(2j zYtpNSi*RaCwS^8%?AYe3i!*>$(@^xy{+!-d%^*(68UVfWby3&6zyrBYj*jK~V>-93 z7*l+%p6`i4(8Dbxu*Qrjr?L{!$EWzrVBiPTVc$bgk8wgmf?>}YMInCp)y=1mAA<`D zLOUHv`8|-mA8-7cLl4tPN%=6_Umh@Wa>r(g3C%OwKbDt#nWF==>Xb}Ox_E@kO@SIU z1^NffzEn(1Sirl4m&;&VE>|sSe%CPCIn)7ljhAKNpdWoe;qr%Sj-xWH&-06;!1G13 zwCvD03L1bAzfG}Ku17+uOuM-R1TE>|G4>p9RCq%+PD!A{w#%`nUlJj~5{zS@ib2?Fxt$5_bzlr?ECF27J>( zv-3$#{pegj@i|gB4cV9Yg3yB5$3?v}OW)bAtz_^+R{vhZQ|ERzkH6Wv%Qo&Mtq%1q zN7i+SbW940Yt&}AKVd$eZ$hGtB^9|krvjQZ_GfcxSG^!GL3P}%09BEy?MbPp z6qBi^6#IU)oj?lXKwjV-Vd1kQ#K=&-U5neO(q_kDIVRd4P$Vw~hfo&k@B=gk=Of?Y z)~T-Vdp!jl5^Fj?lE- zIshfv5258q6|}>9xZ7wO#}gUU9&98a zoe6qsfkq6578f`7y@7*!fB{8BM9%n&n5&0*c%R&^2BQ!V3rLxm)OL1|)6x=zhr1fs z+QuHp3suyfP7gY|ZABAAh193**@hL(&6K#hF2{W7007yK#Kgc*(!)r(-+Y@lC;WEK z&Oj%Jq%Y2{vH7RtAg=+FH;wW18xPsXii!esKz7s0ZB3^}78Vv->3hN>xhhrdH|t@o zQs4sAao==*KNSZxBD6n9fIak6v7oQ62!+cDf4~uLa;|K1iFX{_1oy;kJKg~Rc3BThP(byo-)@%q-(Uq?<70WVmGMv_dgCyK?HE9#0` zixWQW7O!^_y}f5Q7Xj(%#jKS4v{IJyzkxv@f6R=t#2#7V>x!Pco+ch0S-p#2jB3)n zyuHpkn<4AZt}l_>3CiM`Leaiz6`cr|;LdW!bRZ?dB_%C($jdV$=b@9f)bSDp$nqyy zp``o}pGNLIpMAC+pL9>1rX9|!ZAG!$xK&l@XXDDaj?{8}yU zOj*Sd(xP%a>KvCiP{#+#DyFf={{09N2Un`K=;)t9TLs`pe{NyY)m#O{=3Dy(Ojz@j z9-#HfGE$w8y4bD+c@DZ(IrXNQf-{rrF?8Lx+THH2>*IWw@d!qLcP61(o{w~mo!zFP znZEzTOgneH)japK+0z|Z-8cCm5{ObsWxBC92F2MZ6*`SUfFNDn>3tuEa({DU zNjWn=I}VgTkc-HC!}fY&e6+f^KUb6fEZ5al(LRUb0{H7%lP{m;0x~6e*#NyYjs$TR zUE=;!g>NLP%KhZ=_kDhSOd3I69DlwwCCvoW_r*$5mV%9WIQY}Edr3iPt$c3lC*i-> zPiF5nI@6%_;$RT&Rptk6p`x&pW?ETVmZyzaE|OY|4UGu%4hJ2T+A9FK-?`F_HfOus zGo1S1oUKjMpB(8U{QBa};xtb_zqABYp|YBaiEK`tDXb(-xj-FDLrM@r(6sz6lkO83 z(2LJ#K@JXV?Anc__B6e9|pldL8Rj|2hsv9li^z`iVIz*V<@Aq#7!C}m9Iz_j3 zLWvJ~bc~GsD+!)qLXKG9-)ZQhqVg+eR#ziyM>a-VveutJPnx(L$0-sD8Y05q9Kp$B zbn6Xh;#8?e!62aPKR;aaIPGH^v#E3^Hr@{6dfq^!^!>o5U(@sF_7xR1{D;&kHpk;~ z-AqTVoKF9EFx(to9}#jIHh46Hlb)kxwdyyns;FqJl^%^dQXThdiGuUKebn`OMnm=5 zr)areEC~yb?(LG$+ZxLQQ}NIt#=WP)TwsO1zrUaNTqg%m)bYs@nvIb~prmn7ap&{J zObH>Maixd5oDCD;ea`nAq=s9X^I5Nb2o3)|+Z-OT?Y#C*Is(KUN61%TWbI0GmFKMu zK>O(bOZd1yUrX>L_7&1)OlD{XlETxH#5X%xnM zu1BlKd##TA_+Z~#MttvADro3HOng%R$}_}e=7CqR=k0q^iJ3a6rwr?Z*3hINB4~<1uF&gFnOhyFMFFi(BTaFpmo}nHiT7`3yq;x0n@_d` zw+S5FFjCWkg_q=hTMO-W-M1U=)iDyXT0~8Fz~7g)7R*>q!-7b_4v1x>pYGl{Yx89l?Gdp}%tEbF~?OytszXNd^rdLPZ%ibzV*EY^)Y>(pAz{KJ&Ml8Vg`Pp^Y( zZ_nU$L~rwHLquY2zmc7xZ_KR&D1eas5#;>Lr8;KWwZqb*Fd4;b@!V1!e?JC-d+& z$P%f9b=Hh!s*%30&jgoyWBtIAD4>fQDO?=7Z1$ZmYMSfm6WlK$M|@@h@bGb~#ZnXJ z^2$n;$BGB4w*}(ibaAkYHEDN*O34HZ1=RIXufgM}j(VNp2fn|SC}2IkyZZ-xEd)>q zsu#8|lU7Wkf7G~zm9ta$p>o?zVhP5PDlcKNJZ)^fos9F`U;t#d>ea?b)4oss zV?w`T`aN%Z4TZ*Ht%V9--J7B(y1E=z81J^Nf|~o> zM&0^(Sf!2Ul!_`(-0nLCv$r$%W#zy00`%9}Tqa7D(;7YYz6aZCU3N0vkQ5-?la|UX2m<=NT7ypFcjik2>dGccw?}Vrou%AW??~W zeMIX>OY}9k45>9=XhM@C1;>~~60AQhuoD_pu2MHh^wey&AtB=Y9)V`5 zM#WVw1pFHEDVfReKGRp2re0vD-;Ascp-eS!5Yl3%v~;34-Wv|Il99!b3V?pgg-S*f z8xD+j?%x`dxdEfGZhzf>)^@aJ{YtXmzDo;#VHqxIBIz6{!xiQy%G4<}Mw8Ip zGbLO(?w7!3d6drl5q=i4QRu(!rHu=>zXhD(>upy0&NlMFFfFaEKjv9Tn_Zuy?YBsL z75WyBBEk@*jE!MmUOdTY0X zh56o)25FX6J+uN8nL^3TxH{I~*#jq_CMWJ8Nn^8GXFVP80XrO)l=O69n8AnXAZqyQ z@rxOm%WDnBnrd0ph8RN5mryQ5bhh>mWexkYb&=srFd4vLb_60|0QJ_aiESUr52*|w z2Pp!OFmSH9o7cL#VXQUlyYd;e?9V4ZD946(hEA>ZE={fW9>uRs&RNdwvbOM>M7-2; zI_nbi!_y}sL%wGEyRyK56v`}Ao*+~53fy(*e#>LNPbEgITe-0l<(AyidEd-yHK&VI zP#|)@4V~YA0giqopr9~ZCdOfPzDOsWZzmJ_C4^=x>q)Rh+g4OTK!hET>H9>Q-TM{6 za)mI$o@U`;^SkwU{`Rt!U|h1K0HP1i~06O-*=yLFo0^OG~(1(ERe) z=n<_+s5h*%-K|R)4)kwrT*jITW5P}sX<^vPc@s>ndUWq@VfcRMP^QOgyW98nic?c9 zl2LhDi;7jOsXJM_1%|YAOT~09FMti_*Iz&m@dRtn0t66QZxphzJMbOc9aWVgPDwco zNK;@I9*Du+S0Cfg{sn#BKM%T|%9s6h;d^%#c#y(cyZ&)1YaP?;V#XB_xvmUD$YCEO zuGn*u&V6=|FeQ6aZ@Gr_L%OuB0H>fO5+h%>Q)+4r>PNFr=aH>!uWkEq-F!&o-l$04 zXjRe5D0xKAi)*e}DEiiTXLrie!;<+@Hrm6LCv@xM6^EwZV%%j4HEK_QPdAT-f}3n= z*C6y3tbZFVcf8dP8CWl_Qi|eWJZj-(4zu;&HCWKUc=6#&=UC+Yz+ z0yBNM-m|y=js{}MOrh7nx{urGJ;eiCxOl*Kh+Nl|E4WulOxI7FB2+W44@cgqUrGL& z`9dI`Cb}De%*%f-G}>R8KA0|If3}QDvQ=Q&>X|X!rE6pbjZrI=jCH2Y`pfZ}D~nEyp^5h=tl8p>_D{L=3%1PM2F_;e20$zo?bxavpa_hgLnVJ*&zOZEbAC^o5@jz6=ZhwOSq6<;0hn9E_)}G9JW!dN`_Ra5({LX2Cv- zzzo(8A1D|YN^v#STM`m*wVQolu&_1|k+{GDb7_1SKjZCz!0P7Kkn5xUYoV5Ia&q$R zO#b_c1`{iY#r`=k^b^U%-oGI$EXw{2BH2SLWzZm zZE?RBU)%3{$MPcH;i>a)1GYKZUZB0b-4bnbFJu{@bXibOnt zE#nbqP)BRCD<+|_9+@xg0av+Rb42BtopSN9I++!t{Wm4j9MdvBJJ$(5 zrd^I=4ZP3wHuxG+H1Q%OGhN+NFe{!yF+$Itxkh{FKL)KlL#%;yw_zoE1R|XxG`9x} zkQm`yJOe(5lC!XiuFrwXZDVw)mJ|zTvmGAhswL}t^{%6)4VE#BPH4R~+yk}}?MDeG zl#7U1yr;51NUtImK0O}R*q$%;sGV)q*RUQY5?t%Ox4#>}yL&*$m5H)O=};OR82#5Z z;r;mI2PPUB*$_&N*3YC2e@nIKuL@-U(*l%tPffw7l&I9rOYJ-H0hWdHz36*bOiVy* z>@^0~a+5Q$>(A5dZ#&XKA!)DP%PJ&|r3f(_6()assy8^{`RF|ne2df=CLDPG8IwQ@C;a?+JlE2*XSUqnDs-|&?7`q@ zv>jmbR7rSUkn3&M>=zS6?_ouR?G(r@RAWWQ%HNMSb{ioMXek#x8!?_uR#G%L-U_)q z*I*oR+x8!@6WBpSs(ZIgOiYfXNZvpwvj8{YxxKS?6VF8&rzMN~h4C)|_sPQLG-D`G z&{87{B^IyL%k5#}7lQMhP{_s*#+sO6ys6vm*4RXY`;g(Pb;tsB>6Q{O=^8&QCyX1R zewG%6T7i=K@{@EA>e7WW1P7CS=mI2}Ozac{2U5SDZrZNt)sr{Q> z$RAL+x^#@1c0*vw>c=6S`E3)~ZF5Ndvx8Q|abm^;04l#e?8n!Vr;H;nPVNBJ1yc<2uVuzyhF;qp6g0&Y9$G(chIDiz4ZQt*_obRwxWzfu?~ z!903TT)$kueu_upD{Aj{6{m^cNDQ~lHkjJIvpgqLZ#I0Fked2q(D>ndMFch}R(KJ_ zchinP>|ag2E^**C!fj+(GB__cHWuSSZ~@^N;YO?mU-m=>KSisZeBevWpJ|dnpKfv} zg~C`al5>-hG&Z(yzhuwp>C7P=$CiYjaH?0WCUkKqVdDdozuokJJ=}$VSq+4hBg7TO zfn#vz+=>0vcE?<(oCJdfV6Y7Xiv8Itv=D)N*qmb3IuCpOM(q&zYr}~wU51C7V`N3x za@}@+F)6wA`N1i-l%FA2QD2SC%)|>P`?9|0 z!Yap>!v~AnOhNYwt?HUD7D53JvcDlY)aW3hcD~YtASRQ~=w?wuvFDn&{;Zd~rtM*b&~GPoYjO0X<_ZfO_CIik z74ahnP0SRNH)-Ns`BJ)WXq%{VCH!Lu!#qDTpr5wjgob&dNFJhy-=RVMg;z)b3k5t9 zx6>l1{n?`TTsAAg05Z_jwiPLv0+hi@ZbvKftPXcd`%5*J;ZKU+%NiPZyq?bc@6Nh0 z&VgOj>%dRX)BR;!Qj+O4PNBFm+XaEy_4%~~1S*h4e}LV5GAB`XP&R$+BNk8`3sE-V z0&M{!NY9GM3!&9B4xuFn1Nc+|Ft?A8K$uy<@}o4gwTr9d?baeW*ccY?5{hu`<(jzr zaBXb%ms@H1Tp{7dsWp`*&zcM`)=a=;k_1oF-=o=Bp5n0q%i<*YlOz?b<8=o@*Cl2UN2+Ncd^H07oy=yCO% z-1e>w%D6)i6c(0ZV_y)I;>Ur1qn(*UbNai-_tHKohE*9AvD{5gR)JVRQsUu+Oa1dF z3cyP=bWc&aVgZwJI}9!OL&YgY#NFsJJd42qPZ$o+8HV?VXn^7m-idE&eW;e0``i}* zf6oZ9hRgdKg(UBEb3{5erKz$1+N=Vq2le~A-)tJ)`|Egq{(zhmhIz5#HTrn`Nj=4d=M|1$Oq0(akn?dW2ADwKzKZrH% z9iSKFE5pAgrp^&dW+D{4;k|oI9_EPNec08+T7?gX>Zr7>c9nf6EN+~I0Nrw#{|~p; zZZ5;F3vZryyFO>l`JW4xHA7A-kpwPz!ppusfb<+lX;8yt)Ftz=!6O=e_mN3d>`LG3 zVgP8WRKllA!Ue0t|JOe~Jtsj+qX{tKf>3^44B+}r?pi~#UkA|4)ms-^1wYrd~QAhC9Io(iMqaCLQcf~>v= zmc*ix`aaoPE!2=D<`~I%XJ7FpLffxi+ zqQi#Ed`eyKaEUQfLV(0t2Ly<*SZ$l567v#qm+SQY%Zscs?(`ZcRXLWI z29i0nvUKi{7F0NMFE1|^r+o#~_k6gwkhRc?iu>NI@BvomquJiy{I36cZq==3gbCrF z(O?uMI}2K@_lHmq4_$YXkf1S-)mU^wwLND>XL*4LM=8SSnQ0n~7+p%_6mXf(Ri&~6 zD3wjSsH0L@kX&u}Eu)cgE-ZIuR}drVQbKkg^1d*A5B*9{K0Sx#s#JsWv&!@*+-&*B zc;BEDJKJa8V@SGVtZE!iqhAqY4M>~G zJv)f1XSKLv2dYdSe}2M+;3D(#)!Ifg3#CN(v<@=|&_+4k)ZOei%#AQe%sxaQ$V19E!sjbWvv$OdeHh)%a(G$Ph%b$}vvKw*gf z98T%IKe5g!SkcU2$)CL4+)g0=2-#5_nK{EQcx zq|G}Ts>`~lpYXGc`efT%`QSF?WGkr>t9{}T8?8g)%Lkq2z^CAt?~@fvv%0@~GLHx_ zv9MG?Z?4`iw_kpvb`WB)m(gl^>*>*8G(QEyVzz5$zVJ8u3&9oRmtrY3V3vvP`bvFY z?l1ZAmKo#16(otpMPQ{+gA#1lc$AwE#mLl_f;D@|qJbsGnE zW%(w}x70-iueVHLH%h=gePIT$#lX3R*;XqBC1p-^7!nL6Ex-2-^y=d_@h?H&!F7yi z=r*BM!sjl97NHx7pwM7}>Re=oxFM7MwPs?WSABW_OS5Uw3R2;KpDy_E8Ff^eqNym^ z#`($}va{L^#s|so5+0#LIzM(7F#7ro22=4u9(y=*xbI%M^J@%8*1dW#@1$Rtc8>drv~=)OmaT0e5TN8z$30mW_@3tAJ?fy5b43r+Q($vtJvq%im_+jt|>Vb;-5@jFb*T6fp#8ze> zKU>JJrOZKqJtlKm5NGl@6cACp`MxoQ%krnUV`2FQt$za5rLE_&_TJP>f{_@8LM)u% z+k&EFCtj{M%`%_a-+B5G`Q&V_7g=TG672obQGO2BzCmb3 zjzy*cwCxXQsFMB~+8wJF=+u%!-zf<|)n1PaUIlM})5@^RZvd%$r6K%)%s1MI_Nx>= z5bZcDfB9+X`33a!j(dFCWPZv=iy40b!Fb0(`mv@w-xl@X8R9TxeOaA99T<#b9Q^#o06Q-9cG3g zLc{($W8XlAUg&-;mdEQj0Yy_vJeCbC&n+;KgO3c&&LW4uFGUFIgZdbll_&z8?Ir~@5p@*zoaab-mokI&nFrN<;*U{4_~tCjCAzJQV5ZMP1Fg%@l7V=Qq4 z2CtoU)daHa24|nyxw0?#?ku8toh`UFI6ubxcb(NQu`?n&`fH-{fAC>5kpmb*fXi$G zPF-YAPM~;qiOy?YBv$-cu z?hg3PNF`*q-Ri1ujNaUWgCB6X5UduPa8O>fkrHLBt1BeG;;#A_F%&Du1d*SG6Pul# z+4a}RUrVj&=35d0*{zb<*hUFtkNgAY2wWLej#Q#J=GiEF*~V5ji!>}QH3~Abjka5m z$cAvzN6$dk)-+#}x)jaQcY{ypY!pSL5hdB1g=3DaKJ?`)C(?|$-AgTHpFvHNz)vQMo6z)rfz@y^x|Q7jG~Efg|-#;N@Dv zn5s-JRF8n6GvgJV5Z2$py`kA?`mA80)`*y(_H;rq&w+Y1oec^|LTMfoG&JtkFdXf! zA7lysMum}@u%*K0dT{pLZh2&R))1Xt4{JF}aLAGq3LaQ|4-%!A++ALu<=qp$Qpgeg5u&!MwW)1&2xCp1esWMpnsu20+ zvg>k%X!G6%E&H3LJ?#e=jRgyoPFfHqMIt_O6fykF`!t&_CoL)zsfaP@z%AnXJiDc@ z>6WLIrF5S*i&PXh;ma6M`NAuD`NYLz0H)eWE=qi_M;bUXkKgJ47;g(x9WvaEfH3iP zjTDS6q3h1LB1+>=*-w4viAlJz&vSC}LPDwbhZDH~S8bO6$R92o!A@ z2OjVT?||@SNqR~Pb^;7KjKuhQ8plQMy|}oz3nt@Ly`1KJ3Se^sy*xnRkpY;y&SkhS z*)#86DVY(Wf%fjOo7mcQrDLX_>6PyIN^6g(t`IQG|Do!u!>VkycsC8w-Hjlff`D{M zgVK$3OLqv;(jtO1(y{4oL=dE;8w8|;O>dezp6{IR-upg}fB3N9nR#c{to*ID7Mft= znvP4Ym}6LfHu7hHGl4$lH7oq|>McumRk3#L9QPy>{gbP}Ft6G2o$xPx$e;eR=H6VH*B$-IMx|*@;f4(SpwpvP`f*`ebwkQpj zNsLB_DyuX2UDN!KcKFTB1$9bbgT1W9R8(=Z^IJ@e(2&N;&v`B|=S#a$#DYM!R0@gP zTacJ;mjDU&FG8jV{k9AdH5z9~>7$gIx2QOa#Q&%%MG?q-U!h@ONOPsrHYKoW2hHhu?B>;_D z^^3h% z2wH-rl5H`ued`~dtqwZ%N^x`HR)6lo{7kiqG3mv4jWN4`T7^q3?6#kMuHGpP(?Cwv zlEsF@(dbV~iPv*_!_AaBa013b(jn1Cfbz;d{WY+p)#4vvrd3J1xy5L<(4p_FG$0ZD z+HWnfvQz}D)Fi+e{maXZ{v}{Z{pL1`2W~IYhWAl}Iy1<(vHrj6KjnVp&q;jD;K#(1 zr2O}MDZ%;5HM{N$-rvJQzAwS^dZc!yD;a?tHlE^RQ<4s#G7xmId>Qm0#V6=IkCEi= zK$t|0EcIlWP{c~yQ8dgTe6+x=JYgzi;sr)VlnQJG4@Ee~=y5(@f!577--p3z43oi= zgYdKNw4_}jbOU|MylXJ6Y-37GD}t=m{KfLauiO4%=B+q_{Q|oJR4!Y5{k~<@w{HXe z*N!F#2M4wGhJm-OR(pS<$dmsaDq0I*PO>xAf~=59H~$<*PAXf1x0~bSgBP|Y;~X&O z7nlL~Jx$-Fszh{udA|iJ-FJ2LO&8IEF3u&m!3$Zk4_iKha(-)il26FAKW{Cf(Ug|2 zr}9C+xF7;j&^Dtom$ZBY4Ps8si&5Y60*NT3e$;yx7DI9)))(xc+QUfX9L364s4x)a*0;rComm`Ri=?Mkq-VXJ{DW zk!%7N^H!b;E8-ViX+cksJ`-at+fhuU_(f|+VyrB$UdI8o!o{?{-E z6cnp=V9>KVHv1(2E^(7ss+Hl3hOaqK_lRaj%+(+ild{}uB1Gd18pGy&I(fQ_%x$xT z3f7~*;u={_DyYLA6Xc`Fa*l?KS%+)L_Lo-<0rM@1T*zg$X9Y`?wU1~B_dz=o4IPSCcWAgZ7Vuzj`uItnvQh||i3@lkZUN>Sy^EnGjrn;Lb^R2+ zA7p0LWwmtd9-DJ1Z~jhD!!zrIJ+&6e(D`urEC>l~WJ#|D;G^#;gCo*s`+69*`o=o>81s|8l2#rn7!8Np@H+w8y)vDq6vl|#{ zSB?IHoh=6UqMUlpNvHDajP>~;4M(*S_= zv#8|6O02ZawU1VNuBugwhX%K@PDI;Zk*3$H7Ij9i85aCNt@w#(>UB{GzWfzmM|OxZ zL5uHQo$P1Ct}mr{9_ir*MPcwT+Ppy#$Dh`545;=^3!|OHf42d_wVyFxx@xuEN-%M$ z%G3Sw%5`PzM4l}vcXosNc-z$B{m>*opX)8?rQ@`W725rj6~5ybn5Zog(HgQ9=7kOU9%Onz~TxOT-MUp)9n{ESen1v5@ny*jl`g~ zjk$1=gL0R{NF#6h9%867R^(6zzCa9HqAhJN=cxpG{?GcJP^?{gmuFX?_aTs#|Jg8w zgq*kX4$rrXLFH)21By4Vo)}HBxyc$iayGLPF;A*c3wse5WW`Ua;A^HAriL>Jn-PT4 zv?nlZccA`3*CVEW&&M>q5~h0{!?16=nVLj(AH6)QB&(JEh8Y9^w?~0f(DAhF+R`HGf?qs8H$M99K{_KN{JiZK!1+mp?F6o$jNHa zM1@kZN~Po_DdaJc2nuF~4myWo+2y^;JF(rIa|KspC+V-n@V36*!>G%bGT-)g*w-vq zqD;GVGhZjE0H{0C0mdmODuv0Iw1k>1i3L%8%j4-9!vzNc1`Rt`)znGrqGWKkkvy}$@SQi2VfJ{nSE&@Cv5h)nH#J5=ztZvb5Ud<9G(S5OZnUVHV~{>n4MwK4d&NBGI^+4b?RrZcBu& zO+OL8pv0jD7c%85q(KVdgg#^^;#1BwT3h&|u)bD)5tZKpumLYkFyEh)t$7-K8mIN72Fw*ZWjbBc z(8=F@ToF$O6A$JQb`fOql62kAUINC9RVjd6`j(JxdMU!@8(T9g9ASL!8QYH_;4ZEW z$dQbgQx%?rD<{Q{$v$yGh_C%3lt`FHHECml2=aGtp5GvE z3fs^P3*(mlR$C#GotaQX%GLZTxnY9I2KO6(Vjnu$^H;G`Gy^N^2Cg5~Ay8=(;Pf{_ zXA=2aT3GQ&C>&pA-}0cq4<*2FqS%l%6B!3M5rmyFA_^1j52edmFr&GMLrdP}PC`PF z^Ve{)rbrF!=<0vIi6Zb$YsiW!VVE3Z$UTpjZ1lDXOs8X`*Io?=TuUkq0l^-^AUjB} zB$h{bo120n!*Y&9*IaS%pPe!X>yZS}MP{o!`kut0XLr(ac;x2S9~^=AztoPL%N847 z(+)p3HQeP93@-eTHuFD^ z-_&2R(!GQpHois|&r?Fj(5G6wp;07U;iIxSZN$c3?|CqJ+uqW>y~5p-`n zKuqZGqiKF>{Sflov%J7&k>u0OB>Y8?nTS2`8V!*Gb>qL!pmo05yC*Tv+}=p6q+e2G z^nY7hW+ki%`0naOId+xHo{gU`dr<}gE$4mh9-@mJpx0EHb8LQls=VQJP^#;Qak7l1fSGyOE z8p^nRFrBu4>gBu|t}7oWleP1#{kB)n(WomL*AYY?UEe3;6NfpFX;Hl_z2Zv9;l)oS z4M&ni)UebrmCch(F6@43BJm`K0mN<~dE~!HS6vU+7YVerVz5z+PsO5Dmeo*0jNkTVi!q6 zBu5VTuVhQ!cjxgHEzm1wgehrc7y=TDJ|HOwB}q@pJMgsJB3D)Db`o0)=6p+dfYZ&@tpE19thBM9D3l*+asM>IY*5)0q%d z_DID|@V9@WC7r34k}%l^%_hK!7Uz4qarRX1!FSS-=54_JYrlEtvtxSNez zI9a;@8++Mjj@!;9aqX!t1?2bF%eUN!Uqh2#=O^B{_pLqODs(YvKJzZ$>;E?0*HpKi zr=+4%<2j)6=^Za2v%crj>PILqt8!}~=EGeF8b%xiJzJ{?Bp2Ww^y;l&)eIQk%>oqo z%Fn#h&#yo&q8X^1q#0d?fP?wV*@=Cjfq?<&;9V%4BwLDf`2<6rInr5hEjNHbG|kBZ zg`))r$ievwhX-OX=MjUj00bBqcGJ=v7Ge8V;sPAvcS{IZ3 zRCv$vXUyMtYO?%esO;~Ht*#lgFIany3}-|s*#E%S4f(n@yL zgJk(6kT8s*?3f5|-yWTuupOV099oP#hG5;;_Q4^cQpu7$l@>)^9A&Gc>NHV2hYqL3 z?4gRjE4tARX}mu`@vhw~YR~f%tJ}+ihoe2plyeLu2TuJ<(Y*ndT>ash$5X9FT@Tm% z_Oq4c>STYGT2YGCX!?esYELFkNtpj)TW#^E3B&J^Zp@D+ku)0&re8V%Fu;5y22%d( z3WGLspmKS6@(*G(KcT{(e?7IILcizn>84MJOx)}F7e4ZO3TzL9{m7M+eIMVOweH~H zwpMc4O-oK%hqphl9)r4N2~c6tzads#ZwU&-jO)RyvY+a##}?{8V$+}%Ng7|MXVfNIxe z>mQ%_X=!L^&~b6uQ#DaHIkqeem>ewG`03Mza^JXz@hL}B>T)sGx@r5|T~De4-Vto_-Q5?;s&bZFLm)mYCDAIIUii+SaMa00 zUSw%$Db{Fbj?0(UO5+9kHLfqJSoRK@Q#=I*#>CMvsMOQ~%pWZvTmJHgceBNT5KW@v zO>1s3)y_^^0cJ?$&3@T&FKg%YRq(zE_{jM|s zVVKujwU2?*3=-0*j?+6>10|oHwtaee8@4;w>B(R3%SeJI{*(xyXa&ofUhn37;@|f# zadU$}@Kf0~Mp!2`SgNu+N1M~+>A1vc?(Y%wIxX>A;eLn(CZJJyB$nhst0(W)GA_?? z>O`}TIDEb7UaWO36(ePQBf3+qssH{Wt1bUyPliaFx1&tQC33si9TJep>rJM? z-vB5&qLEr8-*03AfQ3;cf^H-{4rh=$uFoS&rp-tH(DLjy@Lv8d7LJNx{q)Obwd;Y- zuv8YbRG6q4-e5k+I61@uRD$_%xDpNxzD4QD%Tw#RpdZ8bzUGboCt%Ju-l2@fVO&G9 z&|WNE@~d25i~>NBngR7|;k5G}An6LdrJ_qco;AsjDbfB+l1bV{MaV>KVb7qh&K+=e zC3JLj27zEv-!t6b_~UY!w%dN-IXXV?J4+Csojtv{=$RvpT>ll0Sz=NrSo=Z$GVpM$ z#E_c?+VxcXq0^2wDCTWPtNHRCF`3w*XQ1y%*v+TAMQN>43adurq}1~6u`yaaWLaIP zCZetyV7>ScZVY@pK|j#H%4+ujEBe=A2U?XgPAXlvbbJP{rjPlYnN~vS@4er6n!;;m z!olDh%>ip<-p*;*G-$A}I9G%~qTc_=V%T5FVk+DDkOlN&c}A?mT}DK@ziqEXIN^cI~vsE!hn>(B3azQ9o71()ROezn9M=CE+X3{0iw}Ib5A$Bh z3^}zK%eC4U6r|;+qr(IEuZP3=xcd4j0^6s+2PKf1{6Foi1dHtcr)`NATfp(e%_Rf0 z;$>>tWfwVZf%SoiAT6}t!l~MKLqsKq4+9E>8IAgxr*oL{ybWytMvL^}o^>L%fIYSe zjSzu}Nj9K=d}0|qPSq-fzZ~LQ<$NtAK$qZ=;IHo$;o)m$@27Fmb8d+f5CZ*{$PbxH z+zqAkzNZAFZR{02o9>JJ-W+hu0P>79L2ybZ>~zX?mPf9@XyWS!dxq$#nUb70cGAyKJN zO|+<7_=ZN`pG%YId|P0t6X;AjP(4h5qQN3tf__~DKH3cm)PIHp13HtT=4VOafqK-n zk5WJi2DG%kYT(Ey0=#;0ekunyNnqSES1PTK2DTjj|MS`lrmgKO-AWzIR3(&39kg_n zM*zlCAn9ipkNl=^>Vp=@m!W^kiM_Am1c7+KmPh(485rFEFB#;!l~sgTt-t@In3NLS&gukg~z&CSH;&7Sw>zNuZmOeIpe+@dr17GY)tU3inC zth}$I*FT*@im#slbPTt{we`Md?iW;k@SUo$IZ6@NJ)(FT(ReP<1cm9@9115B1KTPN z^;`mIw^k5XJbHAB3j!%N171sA!MM~S-fy8fT@#(4Q{j3~*v-yF8}8;KxteYLdNc7~ zluWtK9X`d4T@}j8;QK)8$dAkDM5Wk=z6*eWo@;PokH878Ap$}4QIC@;@=US7&Owo7 ze~*Z^wzhjukZLICw1g_;Ep)as(f{RsH5k^P^`%YTilCGzm61`S+{+Ub+7Kx|#xbaQ zP2JlYI*~8;N>?bnMEZ^A(bZf7RzTe@vw%UCRBf&qHsS=&PEK2~nH^%F@kVY}T{8AV zW@{{=F3qokZ32J+tlM-(#MjpQ3(9dfY=U*eFiF>IbT~(tvF;b!a90B!koLaK0HZew z=mXrwU)A}$BA{KgA|88X+_UxqmnR$WydN(C=$_EH4L$`Ul*2a-KIUz2Zy&emmMkCT z_nyHeyZBY2z-4|koWQ?+xNfdp3xSkr#r2Ll8EV#fabz^v8~0W+GT2zx*do|so#4XXvfm&YI=O|Su<`qfCu{gC#)tJ$jgATf%&dAYVds2NhsvXU**ITd!c z*mUqMI>qK_h#e(*q#q#g#Kq&m89!S4((GNE`o5uI%}THPlP{3t;+V4hdvUK%9 zU#aBe`sn?c$5N{+Qu>fe-S+gZ$Ka0_Ac4s3lIrUBNO~MlCxHPuRkZIg*~wU2TU!$} z!iEX-2&?pj99&QkVdS14>yK$?0I|)O3Fz>5r%@m;(CEBuH#KYUYj^$a*RR(;?fy2; z13rbar$P0nxj;%Rzs)H4W}>lq?IaqRHLFq$G?610*^j{k$Q{bu&HZ7wM_t zDaE67V#{u{E*>U@FN0SqDjbbkefn)D##IUlY(_I>ieB2Sda|Z!Y?YijiMszbN^)X9 z^obbgaNW>J@(fw(65=vyelO~Mn7$1CG4!*ETTF~l$Yq7=;*;!StDEmcmYcS!DJZ`D zsM@&ak`G1ZWK(QZ(bFdcx%oXrGN_Y}$XO^g7`{iGabSzI#+3H=yIoHHwtR1Zn|B%ovrX% z8VMN{d96u;G5pOC|)Xq`u{zI6y7x*i`N z!Ew7!9>VsaI*xbxI+E3SM^SA3%ub-f^iJ8zikAEJ&ah@?qB5j0_|(4op;= zBbBe@fYavY=GH2GSvu%9RKXE&{axr;HH-(qFd!jHsSHP(-QqjTZJ#?=_{ZAc7pW2) z&n#}7TQ#|`nD6j&Z;X70<~z*B`#3EvHov(ifaH2Zi;osA)6NIRZR;;D3m(k(XO_q9 z8z3R{GS?gZY1y2$f!tWZ#Ml&HdzP1}_k|q84GQHoH0X*{0;$p9wBLH=hR-p(gjcUw)!?%50)L4ZpuwCf{u8s2e-cGmlemwPTCM@yJ3;Cwn^uHH`6LxfsdI`ruF zsQ7pix9j!MDPj{r4S=}L%#w@kVNZdSr~CULy;hIM zeiwgYYAi4pF`4^#Pab>M+{AyY+j=$zjWgX-1YrpT^2V($D=Ap zq{6P{<7&}|95N3t*s<(Oip72N%l^@xHou7rNP8iO=b`ia3M8`1r|0DP=(i0%^fQ%u z@w4CJd&(O2tDXDg13OS+Nj6frJ7t?jvp_i@BaTZ?V3hUpzMdL>7QCK6!RrmXqQoS9 zi0bnCFSY|&2?+6HvAk{YZZg39LCTfH=xmS`A1Hv z|Jr6dOAVsH2nRJh(lk3jk_5c~2NgB}rEmZaq}h#CC|9TDrB$Gq0~8m+rdt_NuFJK) zvMf3i7zModOI_}?fSl5AhjA&8TGVS?R_c*PGM__u<=ygJZ@kd=-$@=6!8(M(ekGuTQPnfNa|4r4*mI_o=JdU~nL>vG!THK|(F zSwW`-*?QO!89)dJ-CsG>JD66_42@<5Z;WQ$Ty}Z0te^SfP{q1*-jOvp%y$0(Ffn%a#ozk|bzX#OIUfbmsRtp~Goa6b&x0V6^JjR}>z>?S!o!&MuQS(wiJ2 zSy7a@wW=iKsIu?>=zV{ppUAzmiam)s6#^k^$Cdw%2vodWjpbepWW!`^-vhns1H`DP zihiJoCwy8|RD7Wp6gAN1A?2Y(1TnjGACu10=mw=tA-P)C>yh(y08ExZKDjc{1>YZ& zkol};Tzv-ZI-2<^bhZUQTpbvC9D6>%$WUerEQxrcXRd#q{7ti$0U1g}asqZUR6wJj zQh)Ik2*%?x_r9dtHF4+F*3#e;G3E5|)$RNDt>?dvuMJRk#+Adg9Rf(Re_2%Vh3_TafryuUYMCY^%JbS8tD4@5m#FZh}AYb}0$hGlR*{5jpVoqB=*sdibV|0^rijNQWe%+2$n z;wr<9MIU+`HspIoI&#$qfBg6wg%8c3;(qcB@8FaGTP|tXl8o<*#PvB01p?a1cBdfa zbSE*gyg67 zJkw^=?LAH@en0fsY6*IK`_5lsQ_sO^dl?xtK`J^#a)Wt<_a@TiuRq|` zfctjzNKWJS-d6133w4D!gN8R}NA#dmj=WB9`egArlu`&tM-oU#LIU?|`>C&S`?Cm; zJo9yMH{MMLbIKSfv1K&a$GwY)dtby+yA=Qd=0t@iooSUuu2ZDiT(dJaUuyc%$ysl9 zmT2y@{Y0UmcX1{Xq{^rj0y^AZUSIDH|0S%{)5E(kG`Q*oz(WYSO`U>_4L;U{=;)s= zE_2nypxi-;b{%SRiu){|-A^X`V)dN9Y_W$ti{i%XRudDG%e{TvGiaT=+nbGRRSx~y zM+Nd~-2*u)G8^A8pua#sx%|A!*g`g*(BSDrF zTOFqTu~V2H##XWh6ttHgXoFYNzjqQM&i_DsTm9(K;Wcrkp;O+WcB_76i6<;y+o55v zY1*ZsQfJ@UDcC7hr&32#QqxF7R_o#^hxvC@OM1)C2lw|c_|m^yrYkb1tN4h~;{M2L z%e-lkN$>R?6Sk4{%fRZ>(9|>^=)|w2{`hp-Gda}1Dw^=y)zrt7l*fu?CkDE7i5E(Z zhlz^^Gw;(oC*`Sw^I;j{qFx`$Iy?p-fsVnP|4nixHbpR%}?D(8jwhC zL?pW2$B!Fv{GaLye!q7n=>2IRWMxIPVy~1}{dLtMWlRG* zrCBmhB(g0OXuUI+5+w4WotM)4vy~sG?WaHNDkvti4H=T!7+wAjZn!)^2|BR0@eU|r z_Vvte8XjgJKT%Ipw7v+c zV0WJo-Vv~}-akB;)#zE)c|NFLn`N`}^7b?xG#)LqHA*fxm^MEX6`d^ZXr9x{F<>7u zEKV`3Hmg|)@{cwZJ9sPC2ExH@fof*e0`rE&QzxdD&2Wjn%HS`phF|9DUP#@rW|0VA zP;jo<6-}Nayus^+-9 zC+RpZTG2oISXPc}`@4q4Cw^<2l+9wwHn8S(OJkbj^d&~h2fWpVtK@}?biWborky3> zZO?hHwwRNSpqoa=l`j+N)YRO&jQj$y0inGz2bb~DgT=G&1GM({68A-`OMz+G*ZUHo zt)|}0YT0FfmKe{Df5HUy(66{UW!0o*d#^#lEz%3RjstBiEi-JZ)GsoxYA+ zVtn-IZUGg~B%+_8sSURJBN(=fyZPps=j4bkyQt{m_S|in$uuduZfR@lw^Q$#Lnd%) z!orG?ID%(BD=^w1Bj+Yy0R?M?hgVK!1$O>Y<}|)`g*JRl)jso66NQbnnxVKkZHo_^ zWtY3(Q1j=Y&6+3~KB+DDNZ{ia?bOoJ(cvnd-1W`MnDJZjoHZ?+uNyl&pZELamClDq z<%xY3Iqc-sGI;dyBwNCQ$?mQyOne{vlX%wsiNVs`878Jk5zU_I-1ywjV;ek(U++UX zBL3m!MtllW$HRK0Tideuz|hce1MtVHWi6e+G3xd@ z#0)*%%VYm_7x(=EioTPe>Sx}*?aTKT@zXXrT(7>*jAV#g6xo1shB%A9tayYInHK_S+(x`63$k8qiE0+l(O1l$NGJtY0R6V-qS(oGE0aE z`P3-S5mHXlYxOt`?st`P?k-5$s=5w!#2#)Xh@M1FvKnfQ zVHzUQPxdqPd1B*mt{N;JJWll-xo-c`I9%OhBW2N5Et&0q#_5=-KDUOmPUH|ck?@14 zn~sqO!eHd3Q&e@?18?|sntHwK)U@B1kY=}heSSU54&949txB5Qol)O+E$FjZ>r z=r~17>u)qY{nV|+2&mLqD}fJz)K3py=yQ<7si@Cdr5RPIf8?Iscj+v>zV-{eJmxd@ zKIL4fc1=-}IG>_nLkwBB`x@o3MfzS-+bWz{UHIj(Yv<|o=<^F?ZQ42RwBarNuH3s; zVN#K2$^$(<6V~4{l*;I{okr0$D8q`abAv#WeT)@lA?{NwgZg>cZb2S z)M@KUxwIgKm-|8wpED@VZzqFwoK*L1E{o3h&yFLNpZX4I>2rL{J)BLM9J_9%!ihAw z4d&k2e5L-%D8MKuyHxa5QG?oiy$zgetWz=@YJ9cQ5fdG!ZSAEdIfi6*^tFFr*xY+) z{S8Xs!G)7(gXgeU)_sG%aZvgFJHmKP7034^U8kKkrm=l_x+Xz=rw;eGvu8HvjP zhnfZkWuun{@L+GwCqG`<8^nm~wW<&krZ-j=>|sSZ_Pk(uW-Q(1P{y-B0TlQO|3Cb^56qL8%)~ zkr}!p{mF19Ug_9r5P zi^&zJx8`kX^gM>+X7@W+#dGy-au~~}7p~K8jyF8VxM62@lg>^1Ri>-OZ5}yHtP+$7*kiCx25PnrC+O)r8ao1HT68KF85S^Tyg2T^ER`G$VPjHL*123`L z#hddti=CN_Cuik1G~>;`;>V_jJH1;z2G^?0njDKMR>smiz+m^e6^&}HfD5rhJJf>x zE~Sk9R$8*hj%wsKJY#1+NWEQwvJ~+1KlNPjsMJ4C9lgF5x{Zg!X%y5xbCpk*fr@Fq zh#w_$)RQm%uxa;vsu8D049TPCWmSwYFR5yjV&qQ_YxP>spSk)o_S{`3ZNS39!t?f+ z|Gej?)j~_%(>IQG&J&u{-x? zmQv5Vu;T2ijv&ujq}GS~$kgPF3UdCU{TTMna#hNvogOsWBy+M1ff_yUCEwV?_Klz% zL3NRq$jUC~}m>vNtB!+p-StEu?X*|{+&5XLRg`K)@vqM-qs4@)N6X}l z@SPYh1dkVsKXFimC8wb>5h-bTX$s4*eFM%WBScbTB>>L2MHD}=Q&F*^PJ?J~U)Er;DA@n)TZzwW zcupztmX*EjvoE2&HOATQC7mXPqK*4&Jz*57!Uo|Mt@l{CXF*}dD#lj_P}t8rne*$_ z)w>CsV3)DkpGy_PT%Rgwjr}`Dv+gPr#V|w0=bQaf^PP&A)!x6?lyq(~q!e<}RMYur z6BO9ASh?Ib{2?V}x6RC@UtFIfLOyQKmwu(J>`qBt9dmy*Ck))vrfsjb>7TE4jf^VF z$}aYQx|o(KJe-9Tsif~rTC1v7HaabqHaC;0e&P`?fjew`6RQ>F$ap4Jy@rGYZ7EeO z*R2>o+YMJzioy21856rAHTE6Bm05A76JPbxNZ{f)uu3vtjSqNWedlNJW$sM>%Us*! z>VwF`c(;V(QOA9x4e5UJ1IDUWyh~Tj3zlrRc9Wo8?f;B%;;(O_Sxzl_VfPy#+5HZG zKP^wqAcGbZ5yAJfyUo|^=-`?y30bht*ou!KF`5rNJ;o}$Nzl%=3F88kQaW!?y;OIF}||g_Q72?`|myj zJWmrK=d!v{;U;xB3eOQAUtPV$sdYpBGh#yivxj-R8a)BupU7Q-S63}T+t$|B$WzuX zZ+p$qf44|am@N1B8S}$fGQ@5;M(#%YV`3c+c!F$>Zvc5(d?UGRNdNe;ES*0LcI0B` zT6Wz{PfRp<71=}hgQ1UF0uckVee}Hj2nTZkwinz{oYi>X+=mK5A0L1CObLNNA_{MB zrHwtlTlpQk1W$||wu|OE7;&ZDpN~Bh?+2f_le8d5RG+=aI^bL`%@QrwGFoy+k6CAY zEUehSF|Zd-YVtFqf%2*E%bG@~)zSp1d9vmVB#Dz(rwl3V|ma>N5Fw zRh-)r{!DMRq^wK?yp!BxAV{Xt!@>7Qh+5NS*8iTL&K#)+Aw-h57wiGVoRFHj5@zbE z-MwwI{d@0LnTxtR2J%j6VbG)SOQGHVjFRf-Y!*rfb83?O`~r`?iWKl~Wt#|wSv*`= zX~>qE{IRG$X&1>2H&+x)vb3VVTH{wU>mijTa_9euQe=h$M`{iNL7?OLI~xQms)jJ8 z;c%F{!PO$YNM#hLkLz3*_&)?xomPyPizf?zG3vLiy|K>tog19}a~pcD@0$D3}cT!-c;;RXDvnFK>w6%K@o1}rP*o(2%?cN$l~q41^80c0oNAaqhqA*3xH8!0>)} zYbFBQU#kI@`%N{oV#X=) znMIuYvv%iuFNsNQSn25nm#pX!1q1{fPJg=zQ*o(^xMdI|r+_IUFeU{Wx>oX#BB|_M z>s7Zlf^`NM`j-E|<|e13tp|eJ=3sXg@J<ao3&qtoR}^GxI)asyZ^Hqo;5Jd)7_E+?ONA@&TIQ(KK@s!ripn^ zC}ZjSa{6{(?v4fmMMhitWiqpBddVj}Y38%BJnOWN&J`0U$$kgI;~bL$ZJF@Z;N_6f zeH@Q2=a4bstc$D6#p%w`SR!u&Xt#US0u&CeB6LrfBk_ygHbwuuF6wP(y8H)&ihlbT z5fd(D`|eqUC>3PXze@^{!Y8CG|E@q?c$b>G&=L5#tZYxfUMq%=FF7@nYTz0*Qg~9p z^T;d(lw$u&>H3vAajaZ3gA)aP#uN-oU~TuE6)%UC_inr1Lf`6JHU~Zr37%WKQYSTk zJ9~~0j=kp*2sf7rCMzVJl{c-e|gIP1ff2p-BsX&3@22Rzz>C!e)R*oP0O)qt@>g_A}>@p;QDJtj6m*I6o$ueR2*fe#Vo?)3Xi z*!6JamfN$A?K7C&%7dB%vPTBV6HD{3)<={o*s^ou-dU@RuUs#-YFmc1NQ2Y$D2U0j z(f^^4uu=O4Hhv-9^p+NTJNutKts+ka1qbcC2M?^xH~XR=59Pmm_r%JQ<%#fPIbK&+ zaE9zHc93%|8RcCowmci(2E1x0p|XNE-m-7 ziMtN+5c-H3ng37^giKI;-ftYVs-MP(T)so0&bp@-yP#g(gL%)5d#wVx_cflKKEK1F zy#D$@#e1K-;qHvc{@Qt1OZwE1Z|diOKLT0Vf4>^S!!ae)c9w=a6!sb3E41c_inMEYkzSeU_gB`-^FXV@LYwvw+pOfjlme0bYS>(~ z;LQ~bt6vhw286nR7+gk{H=@R+U^2OVQ&1YliFNndtY>U_>~OltUnIegR^f(LF=T*9zuR} ziB3)VRHBwVocKJBz!&qMhb~`xN_fiF+fU?Ihv=M4?ckAQIJPxtQ(kQ@14;f>AhsAW z&#*fBa7YRYP955BzI6$~+nS@0eF}--``;eQQo&qip^JgGW~AhY>T}~Oev;;4u=9=x zY=oiV7iW%!#?#B*_uehb%Ae?7X~wG}%p#iE0(*SyN=T29<(!10tqX7$ zArS~7S6xO4j5UsESFMo<9-6l~iG|tT{LbA&;PII6HU8&S2p&h@&ZqQXWnT-0;#Lun zJJH{l7*+V)IM`;bdd`dIO|Z`2r@|hmy5SYgL4jO5{B!XJpW*~%Kv}gu+{TX3UEL7xivA0TzGYlgya!6yB`K+ zs2MNTGOu@pnlRsD9e2y|WAdVo$kAZWI*B8v86HRk+P`E_u_vSE>%D;cm7&i#9J_NL z`;0`;qf@-OnqH%YkczOz@fH$;`cPF(f~j5yOun z%j}a{I_h$qB-4iae`$+hrv8?xqs}W>L2rCjF5-qv(6YGSF2K1~zW5uP;J4qRBHeAw zFpcgudC#feo^EMaimtqZTVGggL71;!USE{jMboV>Ku)-kwR$ud<&7F_G2$js#le28 zABpVe|6T5{{7RF%`#b|nJs>R#UcUBRSG>yb+_dddyLl5`1J!vwX~_4(8f9sHb=EFg z#EH^6g$ek&lkxv|1>Jl_&N@UJ?~vZ*l8_%hc6z-pL&BIBKzdu zQK|ZP41}KFEob#2zA}*t6}bS;``qDuF;cI0D0K03wb^_eDh1h^Z~6w z0gJ&Qq=JXL0h3V}>;4crs(-hN_cPWN+sTwzGCfMCX&WFS-ZFZGFiipbs(D z_r-Tr=y&S~kteoLu@BVuD`Qllf^8UtD#`)qtC)~=Nwa^hTu9W!#QN$;5KJycG#rJR z|JLUtH_j8sPsurDzBbSwrVEj;X^1>ICRnR|=jV<Mnv?`m1CzAfzxLI!%z9WW!r}mF31F*qlB(bojxl{gM0SeeYp6|U)mYPq| zk<26D?!YwtO6di;^- zmi`@uS43UWvW`M2x~a6PXI&qfyHV`T;1PkTg-Lidk zlDxG%54(!!oc;B!)BJ6FXa6dzr0q?53eC3N>T8;0dIj2Y{+x`*!5fS2} z$09D?q#9=?F3L;CfdMWMtfwl9|12~lO0be{o`qwlz1el(CkplC$z_ET-BmdD?swko zi^{`2ah;i24avavswO9F$8x5dQly1Z$Na30mCNF_? zGAsF4vVIl4DVYc|ml|kAIeCOBB2V_hWRlnuhcfg#`g6a%O;|g1e0Us^k!aqmpXf^F z?@jlc6L|!({C`jX_=NA5r>uNtG54Z((gq+UPn-Q<5fIg(O*cbLCHo{6yeP4ggpAZs z?HW=*==T|?G>+dd)2MMms$CrtA@V;Kf`yru^O0K}k_$$#*rSI+dPF%A+ecGoJ0;J~ z7w>yKPSAKn^15D8qr7xs!M1Y`^T~n8BL3gE6-d794Tfqdnq=K)Cm|UFqlGlX7#Y1I z0`;Ka(e=;uRm1H7bOn~nIHn!tj{8hrIk&HB2X{g!lCt#wl>^&_$CnpBb z+`yQ;3$t$iz3wxrWAgNIccZmsO^I7l!3&!b@w;y(!Q2p8nt!LKRCEoAep7dAnVl4Qhe-3OZ}_8cfE74+vfZgN&=7nF!}`TrvZGd=RO)Gs%kLfSQg zv4E&{c;Julm~zH*PaC=Gwq0)E-g~+9t<|nJBi~JRUk&{czpa8qfwZ@ONPx_Xd6Q{B zdOv<*>Q?K!LkD6GYm7*x?wZg-ZdNIc$b2Nc_Zv-wcBH&fsf?X2>iG?Xu6FKU)rbf0 zC1Jkjs&}!S;T3&HXF%FVmxW^MwqX_yp1>e4Ub!R%Qw4&v6V-c-`i&+i_qo@Ilj2L| zUmQ;hjp&*lv#!BuBrX4^v36Gr3bJcT2nQ!KmFD%AmSr$E{Gax|JRHjQ@B6AGMbd)G znk-R-EFnt^8bbDc5827sMuQfFBx5W4zAq7D4P__$GBG6k&TShphWDI``+kq(_q@-4 z@ALd|U&p~*$INw|*Li-=@A+Ln=k>ig9QUC{bG|C2^zjHX&i;q%l7pr&{>bt~iL8>k z>5iqr;ufZdVD0Whl31#UGHwzunM4OgSk}Rjl-|Z*`|a<;FX-j@=o2^as|s6HZ=e~1 zP6-=KQTMiFJO#8JynoS5m(&B3>vuxpgeY-Ll!_wf{L*DFVNQLd< zwhkZ5SslLa9y>qmDU9{BW`WxXbHt@Z{5*SXLjMqN<^IG#;&UDM4{spe)T?s`u1R$) zuA3U0dMr$UcWyuwbo&pHQrZ@M&P-x_X9O*VA%~vra}$IxMJvF1JM8g(2>2Z-TS&@# zf5~_=`uxD|j*^{)nC~AnV^8{ME`cgok@*VLskHy?tDC;Y6l22=V797fd=T8vjcQ3? z+y#wIr^VD!=lUuY`GVr9Xh2cSeLhUkM9%)TEWoWSDSPIfOr@3V$mK}xMpbpEF--4F z}|tkz14gb`3x{m{XKj^&;uz%irCO9i3To3{D5uS>Ng7GKYcB$HR52@wQ$mhmY8X{V9;p@?sNJN?@OH;l1Um0(2P_)_THf9%!Xy`iy9e@ zdxCj$#qAkWg1cfT1L^rb1uH_(0WZy{I}Q22DEv^c=VC3UVevjGTEj)xP_5_Uz=9Y7 zhaESUBMp5GP(J&LzcVncw8xAKAqDiOXNCG|mEXDH3CV8eEcaa0CIQ`APS;&U+fs6< zhF7+d>^C{rzX&9$#jhgSFcO)&Inq=^QO9Bf9k|NoJVlaMCtpdbpb|6EiVFu^;o45B zt4E&<6yDinhtA^;2nBsh=E%O}h(0rCh>^NxGi0juqkig2cy3#e=K zmUq!zbjt%69bU;N4jW$-5`0}M*XD0H@2U$?9;D?|* z+S|7K@a0iooij>(iAAkuI%n_$G~Trr4oF7ps~+S(q6Rt@VEa_b(T}EiEK8%BMu_sc zrN5?A_XR7t?TDfNuw99h(7{q880#eUg}J?nI@1x-Rv^z8)Ov2X^p1u__#N@A8e4@> z@m;NA)|hL6t2)I=pg%zd2qL>+p%xdz>27tu?1AqMmN~5TKYZ)bhuM94>b44Pt#_>+Nn{;vUvB8I= zt{e~!`Getb(Qer5cKpc^=(8~Ij40m>J&D`%!_Fi}eT|#ARlld}T%&nT0uk=)cZwuo z?bV^4MJ5V3{U%}<*K_t_)4Fws?(}IAa6_2pTcaoyT{>X?y&m_aC>zQ{j~=(X;5#Zp z3O(Bw^$?;{fL< zoK+I>>|7>icH5Vu=U451HanwIrsEN}HAfu6SydJNK4N`d@WH>{a`8o>Lci#fdLMA3 zQ4?KA96O8)tD7dvh)|oHq`oMQDB|ar;qOy?`K`Q+b%+g`Il4apmWE}fy;u;pi$g4E z>wAn>Iz%3UYEK;e8~|WH?F^~gn}PW+E6%NdMxz!-c@9Yl?{fx~63C&SX2PT6V0 z^<0NYDB(c4yt;|LQeF%(_g)+2Ibf-mO#5wvF#jLh1^l=_RtS>%pE-TS3lhaMeVX4p zpC1i8mO{W7c*w_lmYYZol6oh;uKCmd)04xllAWf(;@N&o2t6@$BrZF5a|D0iYrE%$ z1b(V|Ju9NBI>&JFuoUY)yGh;CE^_eazj1>V7D!t?l8^4s#ojc!Obs!2@2>-9lZ9`} zS#8ns>x=T&0bDIH;@TF-xM7zoeSJxb1xkJ{I8_Xb!ZU6Ij1;Q(TQ6(H@Fkc8{*$1P zpe4aqAuHdWEThV|L8b#49TioK#45f|n{|5Hlg4fJ*k)lB5!spwu)bMoX=p5Nk=sSd z7L>}IEkJ)CT(fiSh%0352w_d{$wZ+TvT}wnlPe8r>`KUujgx~FC6ySVLlg{X2iiZw zC$Z{E+9c*{b9xk&O-)1N+_&v@imh_rNFbs*+(!sY#iF=($#6VFi5o6FQgg;*GqR_U)s5Sp z@cN)AA=^R|u%#6Dh3&~V2010BL@}=|RpiQ+CSoO36QEAaKz@DLS#xfOyoxikIGM1= z_*Ctx=F?O#2$+hZVgygs#4RO-#l?8Hv4TP^?(L3j@>|BuKD2H9&KN?IlR?7bfbPQf zI8%J@Sp9PAqRZ9Gm-Qtp$HWkG{?#+xWwf){5s40`rR@C5#Ps;BXb!5T_V#WD*Y8QN z&;ar2ou5(hmMy(7IR%BT*6Y=I_MU4t`d&y`eaKe`BoTid%q*pPJfA+gWxf%!^Ho8G z!nbGB@1wrETUf>qR^XT7=Zkujl;QBOI3(_Lo9N=Bj)GGXT4^mUgzY}@lDR~`<-V}Y zvm0Z9`EG}O<0|)d8wWpm<=$Q~%uVf+y zizCi0hX}y{DX1|Kj!qn-`vfPq!A@0P)aDWKwFM^UzDlN<%=F!??Yk%W+unrGv!p%jCZq8fG zB}Z!|)ym4sxj{QOwli5axVz4Od}H)j{7(hRbFX4zY*N!$<$V+ROv%Gy!e&Gw!eUZJ zc5pngPgYk%w`VNNN4MQkDJWYpgst!;zT4GXZTg~9-;$k|$}Hw)F7!+S5E|gdnHZ<4 zG)`6axyrTbOCWo_DCQ!EO0p5scNy?0|M6wuA|H!_^mxO}n0yr*NG(}o4B~O))S_{0ge}Rb@@-RY#6xZA^18bq5LS=dRS7 z9@#s2h|1+}AN_;F=$ZQZdaIpM7IjU`ebgI~sVlZarP54Zm3oF^$Hq*= z^KX2Vkw<~IV;n9QVi#&yL;Mr;nu$t@niGX}_hG==0t;F%HMK%r*&x%0JhCWmp_ueJ zt3nKKdpbHM<{C^T98-Q6jIGew59kB)uj{exvp>%Uueg6QmCc-+rxWnpIgi}v(}_17 z7X_Y8H8#dFIXUUF(hi-U+t&!Z6MYOhm{ldo$lB4~q1K)0I>VjzZi6E)a7W)9 z35kjtTN~^aQt}(fT&n_Qu{k~Q0NG}PUaA<=$kj=w-Cb46)&6L3{P^*f)>dUZyEk%j zJF)_-?Cd|$w&y*Ik9Hg2ztn^0ODxvcH*ELnC>wCXbp8Wm6S_;cuV;KKH@_34fanw+ zep+1k@gwq0o7b#5vfxR0R<^Z($vvGC+putTlBbf%xo4}cA1*^XE&YY}V~WJu&Xr9w zsT&(tvCghh8(PhF2Yc9#gn7L>ecyxAHnAzMTfF5f{o;V(e?}id_jo|)_}5YMw#1?9 zjG4LlR`FEyi_?_(r;f^qXIrfm3SdEE~K;?k?-uR*dyG7s6JYvlM#LcxMiMY8Q zZ**j2^QGoAPLUablx@k{b=t? zws>^xV7Xa^;@)5mPxU9SFUK3NunWlqj<}C}%y%2R32HpR0%@w!V^b?OT3YRA+Jr|| zDulSX)hR3PwniY+%3o|8*`^=n{BLkvkyj@c0hB|rk=~M4nzukv+a-<&rXbo0lapF z=N29E1AM?+{H{_`l1-HG^0C2>=??(JD7`GQt*4QR2cz1tW8mYnMMN2anxli?>E`bK z0t<<5cqw+y=U3;_?)8R-UvNu<7=H)poS7MRAH$H7(dr|k?r>SX$_h+4_5FsqT?D@xa1|D&sFHO$Rrq^37$u27HytXOj> z`_IMJjt+*mxH-!H`6zeEu7v>$%OzJH4Lv>U&b9WjO%RQ5c+LHn^$oxiR(5{XkcAuz#-o2zF4`i$I_6QaDkZ(rWDA#C{25>1QShMS;#qiG`@h0M75%da40C2X*b$OiWBVF<{{+lYd9Z3J*D`H(6;{ z*u7w#9hhe7n(0cu)6WBu1nhhIH*FY1YzrG`sND>N1%z6@n?$k_EjM7F0n6>Lvb2Is zm`lZ76sUdif}S$H!|@-+m^fW@)UC~oeEZJtpC$nW6=;?SRyKCFmPHr5-uRQUBFi3) zzTRHk&s)bR)#d}QYh*4NAxoy$HJH3>0s8E>3~>0iz2utL|I&Zld2_f#4n;JqL|5ue zLH2$w&hSOBcWf)>3TzGx`hSwU& z;ei2d;xZGkR4JH_ldPJuh~jrfsi>;1ueRpTM~~dn)kTLr9v%!rr3{ReK5&{gNMX|7 z5C`L({ZFP@hd5hiS(&!iPVHHpO1DhbW|M-)-4iCmZsUDiTwLohwD*w^rQz#+KcTX+ z%&0)f?pu;9BOxfxV^=vAn01KBN#P=QCx6!2r3$aS9z{v%t}bN+Za`LGz9^Kf*rh=d z_wA#oZ9gYstl4klXS`Q>*ZT|G&D^e5jX0HfkEiITsRkY!3bFW&8}R=3>9e%erOjud zTlj^`z%;OzL&bS5F>Nn=ybiAqAL(k%uS`gf-+ciJoo_S&tMS>9zBn8szUL!ibNH0= zxPs<<>Q=`r4r{L=?Vbv(v`ZZ#pL>t}`0Jk0@40~7{DXrr%Z%lkp&UwTK)3Mhjq1U= zfdFBHiHHoyDZnCrfw``Ta4G`>ZhPL)uoqY$&e-dAYL1Q}?27dH_@(N*X_j+s!n9jM z<2BE$2wTm5aPVa7rz=`!78aafC8E@BvKwBONrC;pjU1SYwssi}k6w~}yM*p^tZSZ3 z(8bLBSjQ}$PwR&lhjsH-R|7x}*TKyMtkYjdO>5opaR5r3caQzGe`e0OeUCv*PTg=M zVP(8=COf}>o4&QZy|*Dq7m1^$rRBVSy#%9^S2gtn)(tqAi+eaXU{#J=uQX*N!BP%| zwj1C9=9s0dBCZVgoZMm_{K=z)Y`)Q}fq6fOwj zdlWVjt^OAlfcP{k2L}w*(sEVM+~%2u*Im~iy1cG zZ@(&HKU7+PN>R^#ntpM+b#1SA12fF!*CWEb;S-9TjHthZVW+a%$^0#jq^h-Zl~JsI zwHK!3NM!-$n%>1Pf*b$9`PjVRe-DGcJ(8TjtCVTUxotGdudb$+m6W8iHoYgCzk{y^ zc4L$daLA~sspsm>2KRj_`QGQp^fU=TJhwZ%XdZulUN1`2voT>ei9M?wRZ%+^nhqs4 z#B=@Tl=bL(D>(C!|9#4yJUX)vRB=6J%F4snhn}>CKe>22y0fMf_(? zGKw*rb#lsl9<#Z7XFRZx6d9axC3>n24>rf(mZLldZo#@IU}x8RZ&YLQmk?5$BYPiI zR6+$!8{os9jcwbD_PZG#OYWUc1b+_3?0CWgX~+CS46R~N5O+YJ(hT7qber#Mt#b@e zb+6nGv@#8O5r|q*9K{ORh4p+-$W&eXqTiB`2{h{Zx&VMtbyNX5*kaMDj*fg$yvCIs z1yv3e!-J)kflmqxZ&{x%9kyHiuAdeY^I*V+VdS`kmg_?gT!i)d3n%eqk z*P?(`@BM0|rDbN6h!dh|$@p({=x*#}GiP&D7;4DWBQekZLtnp8%PgF$I9iHCYNWvT zph0eA$~BGbmaA5^`X_t~R#z{wrLtZXl8_img=#7HE#y02Op31naFqv+{_U`*+cnSE zpMlenapc%scx)uolFC2Q8J9xCJzm-^#}N zb|t$I*q2nvC!Lj*qw4I8EN%VFTj;TQNKj}%{h``9Vw-_Azc~fEB*OHiC%mqW3GaCNkIK;HDXw+sYvTqgU)nU=$R_*6LHT zXxZAn5V9Z0&Kc4RYH6q3MyQS%QvOa_NYxb%=J3bnIYa`gc=Me1OqUxXPk0O}OVHXiGbcwT&C<8x+C7NqTVk&ko5`0IK5U2}b@axhruOc$pdQ^*zFFu@@XQg+Z#m&ALL`N>jb3Fy zI%8(}ppN>|aB?mi_28JxRUsiAz5?Zd!qfEh8V^({({&XTxC^ndh1#|k`MBeL33AhcP6t?Yi66|d3`+K0$!U(<|)=wMX*6ljlA4>O!MRup9)rR3-lskwDVH# z-s)BD2a$>r=21z>$zSx(P=!#0=8qhLyp7Y!aS0J#Wg0Zu3R}|Baxi&vSFqs?f=In* zU9wG<4Hh}M`Z>H5#hSICi3)R;!}w6xeU`Evv8vDM$A{Z|KXN`bLhI z71xM&UowhHv!bN$jAOu>*%w&vyt_pm+!jfMJ)eB_=+_wCvPB;z3(}#pb|1b#si=fS z#O2jZJgRSKY&HM5atiPQ#C*6^-%fPL!Y#i(#WDfB<#7!xIVCc<-y2g4g2_Aq@2G;;Gr)V8y zr9oata^Fh<{AKj(0^+~@0124)e@}l=<$og`e(o&}JR|nbJAsf%%NayGz5mBOJ`Q9z zIGBxpeL$?g{VVT3>ig{eh S#;8Y>LojK@dwF+^p8p?kq_G+R literal 0 HcmV?d00001 diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_images/new-role.png b/docs-archive/apache-airflow-providers-fab/1.0.4/_images/new-role.png new file mode 100644 index 0000000000000000000000000000000000000000..29cfc6ce30ef81d537c0967d3bbbd6ce9b4cec11 GIT binary patch literal 14115 zcmeI2b!;5V_UBEBnPX-xVnHghdikTfVGcz+YjG39)W3TUf@4lO#_TQCO zEA6N>s`+-EQ|Fwn>Yi4ALgi#c;bE|0KtMp?#l^lWfPjGYe)KJ&K7V{it98nOfWS1E z2?@!G3kea*+1nVKSsHlzpBcW-50la0>z z%O+VKlWG>=0&f|#UkbXFKxRIrND?6FItq7I&^_5h1X2YIr$i8M-oGEj8wC+;dvzj3?b?AyW%v~PIV3ht z*jsO?i0y7&ff>w@Mhpre#fZ;^%R4oW)H}9z4B2B~oGIxHjW8_@9hYM?)RQ2QMwX0P zKT#M}$j;ogOEaQyjQ&@^u(`~a zr=j~~y0_7eM;bLxWBY(C%jnbQ71wP{HF(X;q{cD&kobNmW?sXmK(pU9uG*=UWAqa+ zN#o<+5mo^Jx#bsey_et#rc1DOLZqi@!LL=I4PDr7&%W7G+A{ldpLv)Anu)y??8(;f zngw~dB)h89WgDw&oFR0N`6fKi8(j)6u=4z}Zj6e+x*owflMoL)ugXDialn5{WZYn( zf@BjN?9s%LARCQ8PAMY75rVm8L(KWI*=I`q{G^b=Yx`L$Pu~X#j97q16@h~gD-Rrb z=yPeeyBvf>mvR-Vk{@;z0n5+cO$t-+!Y)o*WX(^&P4p(jJY9%35Q9zLqHWRCC~u0kpMgwqYH`}q_BvJ3f=i33_2`k*`T(zpq%A`r2={F3vL$`dxRhkn!U zi$JU#6@^y(r!e2^?}6Fda-kH+=Cmc4KcY&6S#!DMc#Ci-D33{xQL)1dejk~_)-kUj z;)U*KtK=-^NKPjles-j8!SMp;4Zs)j>6K$h#dL^34GIkH{;F5QD4c9Bg|`o}54MkP z3~_@W-d~~{S&g8|Z%M=UsTD>eY|Y=Q+gTs7s&~l_7ojkUd9Zo&o2{iLSp`%hjti6v zx(gn=-%AMjmeVDhD}g7j_D}k*q#eZV$<4~0tZi~AB|oC>P^530DE81AP>@h~0Tuzs zJrMG~rc#bXB1noMC!uJ4#@nB^!M8O~Li0rJztWOji9hAR%plK@&LAD3s>NE0+<&Df zl^jYNzT1_#*1Fb!3Dp0tr?5?t5Enx2m<8AaVFQz23Dk8aaaTtHT8X5DJV9DZvOFg<4?$rN%@k$XXJ59QfFDfC`jq(;2^4tB$BNjB%1YWrxcTY1 zn)#mUY9)ROj0$?idBv9UoF(=ed$lErC9PDlPI2b7$4>Kz<~MW6<~;TK_2~5)=2`Pc z$Lq(%$E$Oza|GtutYa+b7KRq5^G(@T_L(z02X5(Z{Wnn)t%cAQsb)cD6*GX!t1Ray$3AKy^N23;Q-bii1i-PDQ^W*0u z3CD+{`y-h{tP|m5w8Q#C-Z}DP=3CS|mqVAMXskm_2&^(TQ>G>pF$P0SGMsa!Q^r?a zL(4B#b<;)Thbh&mjH4WrO~a4A(EWYmhWX;pH?j*m=G zjUWG<_p%VS@HqiHK{#P&GiJk0qe@F__@Y6u>eO)7P>GRBze@{fy^O*eryH`))k<1Z z@qqM*^{NFH`TGjB3Dx%!3WXw%P#9_2_i?y$R5S3>P}aMXTq);WrfcroMT@+=a$Y%FGijzpWG)GPwq0EB+ITzuPFi$n>(+ou94i* zFCRCLcAE!kXJPmDPJW!uACw>B9cdi_heRjIhYN>I#ug`B5^M?y2I#wN(l!Vs!~6AE zYX)BNUKbx-AY;ILz^TCTAyYqvfpPn76251j2_pKz`+w@TA|ebxtKr?%E3!KrnbJWw zzzC+RP=Eb8#%1ZGD$7CZDg4-d`GAa%tU-J(n)+RWxHV@tH&KLD#4F@Jj4nKJfF?u@ z)qz!+B#~ehKR7%*tTY@)XS?0-;8$$Evt)SUy0&o}jmh%f9`@*LVwN^hr(gTFDi0YS z*PHGuhBH)aB5!7wM3D^Uj;p=1owjWX01qIa30oQQz%or*O>?F8OLFEuZ`!bN_j)(U zQ`VdG-6>2*LV6^4E@tj|Zn*BSF457`-Sb)8H;3@YRL1X&*f>T)77TRgeCiD4b4^Y% z7^L}7qAMmlj{=mL$6E=huN&e)HJY_0HGIaRMg*hsL&&?g`>A`@BVMToaSyXpw^S1) z74t2niZVpbD-}-9CoqeVyD$6fW#kpITJILVKLpjfTj8g1xM1pGZeW8u zZ-5oWVijUaEKSpH2ICKh7f%}xRyAvN9jEArN6F!(dVbnQ1h$4%U$*E?)Qy* zX`D8mu7#~pExCK7tu_QP1=h6HY@G?NYPd|fe7SIKbm*TL-Gd#qa7K0!cNV7xqh4{r zIbCmgkur!Puk3t)9*=VD>QpW|uDhqnI35{a+wUi4nIxOHzFzVAg# zMN2B$g*+U4z(4rz`C{5NU11PmFg^$$t&)|UL17)J?w~Qa@@qBktojU`94PDT#Nm?u z*nge$tk_amB14_EZXe`Ya5=WS+*Z4j(KC^B@M{9zrTnnPhj0IN{Jek73j>T!v*pm? z$}`$ya#@ltNk+@L#q%0wM`HEIOKEw#b33_r{mb3=EH9lC)?kY>U=$D!JpA*7rc0~$ zdC+2HIJ+8q zL@#c?y^UFvyV$uLd2Lvgx(W>Qp_lfoV3i$z`nye^Xb@q8iL&l4^0yG zp?H-Cj_l4~@u&FQNA*WUwxPFYdMZ9E1Fe9qffp?ULW2bDvOfG*zaMj-2ZLlIWO=i4 z`S~-3-uzw^uI6to1{;6cAd=0JlLuNNd$gbl5Pc>m1G_B12a%wep}qwd&}5pWmxWC| zx+;WzCC@x6E;K^y@+Jd8egX+_1e5cR5DB3qMCaNw0b5#7Hhz!im|id@!zhL~lO7=_ z-yrrPp7`>!(myT^)haGd=Ojk|0(9!hyFfMzK0sca z0R#jz!%RulQB_)s%fQBpPS4Or--yoD%J$_U0ht~T$t%>>`mwyIXOA$8JOsqm}oyn&^owTJLj*s~9RvM;eSetp{H1cq znYkKSs(v@KGO~8~n1hdo3Q=@isP9h=Q(RxOB0 zxalQ=76)=JJ4noQ$YZgf>vx@lzSB}Oe?8Njp%O18i?Eu4$vA4gT?aG3;UZOHY*z5M zSL>$>3!Sm9CzDxaP)4859#TIZm|4HL;PhZi19m=%E&=)AI87$A4kiyC(hoc*9lR$U zDzNeJyd>@6lIXO4S@3OqrT4kRZ{7;RvFEXHNATE7P@(g{FDNvOaAHHz^-7CW9_E*= zGk6$bRRHYYt=6{-7xFv9+YSLZ z^w?M5#&JV^sc;CfpZ_#tRM4=kWkdM=z<)F`T@h$GxJe3YGLirI`O6za8q|kKX2C%J zU-us!W{IErt|E5Kj3|Vle>dOd?;j$Yn!g*-e>G5)WO=YJz06^0p|K#)F@Lu)vJbI# z7<&x%A1$UU0wwuUl>JsxCW(72h)2`p^KW0*&uE!{)Z&z_+cA9u}j17M;bq+f9fxh zb(8)f2}~m=U-I;-pcKnde68$!Yk9rNdXHb!_BfLmai^)Y@p)O5elx%+ur)ddG%F}5 z5HD&vL^iFRQ%0o7|5LWEQ!=?rebvCr{&0-QA;oF-`K_eR*L=@i5`vUt)41)lbI17D znwj@6ed3SJzJH(BYys#mZD|4bP^C?22t=AHn6!*%AnS!QSK54if_dq0jrv205gF%M*0OA3 zIusR?W90-=7hFaz5BI2)!W`)lBp)iQkJeXdg${Zs5t`D|h*6pv#Z%cn8#e4o5%l-AZvg0l2gjv7FN(>6?O;kMsoNQAjlwv5` zF1#+{vVf;1*U>(&LQ0sEhL58CK= zi&n3|juhOze@|n_9qrTlLkBr6EvU$F5fQVZ3YU8X9z%N8rutimR-82V$T%Cmf|;LSfY-iR%Oxm;h> zgXhkNPSESehUd+=CPGGy0i9+O;mKlU694tXWoj|DR+n_`0YZe?X9;%Y(v%-(SY|1?*~$4UumO`d1Qe>){~Kbe<5dla8Q ztwLsX5G0P$WwHG`&R?Mhsgh-DW$L}B>bu0g_%ccxUNbT~T)<_i5R?fek9EGV(dFPhQm;d$5lRCa@+OkBi3 zUr=b^5!iie-nI^PKF|5jsc;~QokyRSo!E2Krc*;NWjMOZ{yp}~b_fI{n7;je&rb*) z7s=&qrco=B)N_UzC&JDI_8(EBDv$Ho5b?r&L{Xn$`)c7{7@H+`HO0UN!6?>3;Jz7( z#+Xd%|8Q?XtRN!yWAdAbc3V^tn-62u9*?`FWp+VB?s zCWPW@Ehi#}fH5MEOdCAR@MhZKM~^T%^aRDhq4&V}MmA|{b=kD#cjc3XraDBWl0aU2 z5^l!}HFSv;UVg9-^Km!X_JHXnIudQ?4%W8JqdB*4qWsRe;-Em*rNwbCK*W1CAOP3|T# zcz@H+Wfn|+7NBl5FB|wV0Um>^A;Y26uk!`QoPPBqxmS-R1K>$O%^AG{tHf> zbt6sT0h2Y`)(GPy`=9`_pJjr^ zuEOO8OHeE`lpH<$DQ81ys2n68^FgtAjOtNC-MDB?H3s^jolV0<_S+z%cPqaxPk-m% z@O|Muj`tA=n$!_fYh+%TugmDI>Dq~%{>{hfehqdS*5II);JThxkh8QGrekal?qHgA zR>U+9tUHUomUhE4u6QS*@6M!Gy?0Dd&er~29^TTMFLi>NVjipoMtAdZ2hdmjWX-4l zSl+lkLVgj)cb~TLT7cYBs#2Nwa?#1Z;9pMcHkwGAGn;a@)~eER8AvZhLF?2$^fjQ- zdW}j&$E&`sp+Q1aH2A7KGpyTNG#WnvkJ~wK{ARm9d@q*(Xu1LfFhYa5N&`BkEg%f^ zX)+`EmT#IRu=oIU>stOZudV{e7@|1!lD*eDjorY_7N?p`*_T}X9LUOKkG^`htXn`{ z^(Q0XNJ)TcsUd-OZenRw0JZQ=YGPhpY2$fZ6zd)bJ+Ww`s}W>?tA5c+jjVIUtieq1 zZ}O9Ty`;VOjoNbY80Ne+^1TD_8M)a2Kz}gI5l@qba{D5Y&`X*j&>5}mO7Lcl5?E@{ zS5bVHhCS6fN8>AWXOCb_%;F5mQLhTIAXSegb z(e8A$^)``?bR^g2-W#83ti)IO_C2$|emD-%I^_mVqizGo-8 zFP20WILSgUWoCw@FU2caJ~~Xl?zsS7igF9i1*~u=6#88$|eDIDe=& z;=Zf0eF0>V`wS47&o{rvKv8Y5t%fG6?z1bg+yT5l%VK#}n zy~}Tdm!`5hLtbFP$TkrVEDgKhf89b<@E>rlA;N^iw#%qU((>r~K`~j!Jz_ZO)Sph^ zC0+Jp1@IOCyA(vk#G9^?lyOisK${cuM7rS8Wd}LEL zg|qJ>h{?RWBCc1y$3?*0xChrM?Pol+<3j6Juvt$;y5|dUl!XiFbcvqZ76CNE>yP02 zM^QE=7~U=LlG%X2dFksPdEqxMkNtkV$L~Axe?={xWr=#&G{y=-tcKZwIdW~A+%2`S z!SRNd7##pd2^#Y0f!b2%wDkme0k5G?y?{gvHl%eA^dPt*7QyJN)d7P%na*9Or=DO7Sn;o_z8SAw_GM-#)2- zd^k7nwu!&dzB>zAV*1uJu_QH!|Cn{m;C$bS$;3%vC%|B;x<=+TvK>HxNLd6;?qSH$ zk+jG)@(SNIsH~Bl+#Yo&v1)z-@4v>3E5IibqcEuG-Mi6nl`nWsWSJ1~TIF#n z$l%PP+|}F-wMDi3#4-ZD`jEqC7P@-jI(1DQ-Mp6HioQ)!x8U!g5rI^(+Ayh!1PXW)G*lP#woJZDlLzH2(O7C0g(Z3)90D z``Tj7Mce@#UzvGnI-$b)KwrgiT(}ZxjNi6KONh zjjz{S<3G|%nR_mQ{rrR?g>-*l&y ziO2buu$d=ck{X<0F*aG505Ca~qbz1uT4Q)( zZed_^qA?t~v#|}2;4pf0JymgFs7Ur=_t`Zd5>FD{NI4?Ch(41#;$uH7pdazN3UDc# zs^Pg(%=NSwB6}jt^V&Za@)o!ZwKi)@NQ#hp+9{2wEaFUC!}4$kTgg7KW(E!-1C(QsDt*^Z63 zY*oJXse;KV5@76S<8xyqLnej=(%JQ#7xz?c>;s5?$vhcGT0>4j4I^+Xk(Hm>oCwC9iu%=~4cj*@HVbI=5IPPBnk7zC7nsDBS zdldxWsHj!;GqUN<4! zRZvGiYtBm2Xiwm%NPs&YY|3sq=cJ4yU7Le5*G(=Tzp281!Lsm?VA2VuJmEim%Ig5V z3b`N}QwC>8^#$^}j?PwNr$y^sS_AGl6BCUZ;V7Ccz#uMZl+y(Re}6tpkjAL%p7pg+ zWSx=cBOwt>$$sg7fRQBJkfclN@KT4>;#_KP?F4K+Bm^d($Y#dXW=~6_Ok{|3u+(q z7*ILyNjEw4eS&<&z6;U`S5R8P|>v7HO(yGVetdC+EmEBWb=j4R8 z7{Pmq>?TxH8fX(o9_=Z$p)n9xlTf90+X(rV%j==u-|EvQ36*EB*>!a#|J~!b$JkO> zU+t3cCo{FOk7athp>^{dov;=YyF_sOdzz>Wf4%52yK`D_h^ju>R!F)xf}eY_%V|O* zzMKM8DUvARxiJp6tV+$&=G=zG*w#GzmLL@!$H)(m^N{(*CN0j2RFqyFR(uq9>#fBK zeODU8PIUdjo{QBvira>TGO-eQ`^~;87CJ%B{ib{~k8sD0X)_tCR>?KevQ0mFyX9qk zGp&pIS0jViq``&Tl@e7gEN)Rcwfh?YrVjXRi#Qafj_ylvDzB>;lL;I=DQ~tmg9Hu5 zdg^x3p?0fiRY8R^LksY`c&W3SA_L+x*@hDaVUaUwSQRW6 zsF%XT8eH!gdk$RM%9^z925TA;;dX zE?O`6o@SCdzDg!-pARxHLr9?fYIe_b@^_$TfKN9#qCEs&4WIX3lBRiJPaqKEvF-#4 ze}j8GLRn-T))+?z(3BZ%)AqIy4QBnQw$*-}Tym#lPhIN1m$+TmZk;E0+B-yU|FZVG zeHjU|LIJRpaW}(WrTnds!4}DX*FAIHH?si!$gM&M43V@$RrH`B6s&TC;3yuZO{Bpi zfW-$>fy77^YdRM_aX`CNL@}cwFriSsIXfk^)(X=I+c$(Njhmvrw0%IU`=vhPnh^@d zW!NkP-3heXe}DNHufEYx^SBqZXH)Ggj*k6gf#8g`(I+azM!NoVK*QJkmV#|duL#V0 zWvy{bum{&*4|hY2y~llQ;DBL@nMj>mf~LH7W;I)h#w8&p$~q#6A{Ln>U$^jq)jAfw~3(elarX#Vo1KVx- zGFNbze{WUE%sc1af+kmBfgb5&TH}(h%C#TSC^roFv|l7V%}$f4F)dhI`s0~F%w`?S z3o_fLe1JbYBAU%%ZDPJc{Q`gq$e@atvH~C_Nmbdro0Z9 zUg(vE`E8>E$x&b!wAwPqN&8wpdrTH<&Q+}>X5zk?o)H|0!#;vz)20`&8;VLkW{Lj% z63qYl8#%@u(BgD*+FNM&G{!uMsq%4^TOsk>9YTKEA$aH5YMN(P1x6>)s1d`%!*6$s zX})yAJPi`~XtG%@5oW#al9Q)@mL1FLBHaH8*Pp?5eUs~og&@Au;I3PTQDP0-chODe zIR(nD+eD`%*cb7M1!$7{&Dhdlg%#5J5N+wC7oO*BpA$}pU)sgjjXvxCw$1radKkSu zY6d3GdNN#(QuHDPlGpNigL94+9>?RW{d^3|7HIihN=%a^Zw-t!DEGrte=AaKdOH%D zRw|Fk;R#rGyDQpT55Z%bh2iy!(X~6$>3a;F^-k zf|^l;G6#`+)m+DRL2{z2hNg32iok%?Xu*3gtLVo$r$bc_N15F!ID%kOyU2S>i#{nt z+tF?*BE6d!uxh4II#MD1A{DUTO-va$F}&*IQ_2xZfe5!eBszz``Plg@a1Vtq)_-0> zbxKaM(mB_zIGMh#hHw7XuI1gg-mUnBew%R%So^td9|5%#qP-DtLKlaJIy*X9QEYCg zA2Hl{V+PJ#|8cYR9=Rt!apFkaV6;Y{d{Jp<^O`|*v4R1(w{+p638cprX&6x2(_(v-Lx9|Vv) zvO#CKTM-L-ctsQN<8%M;u(|`s<#Gss(L1Z3U*AUbdF-t=xYlwztsWc;mY!Q9=A&4w z^xUJi--%>T)joXm(#+BZ+yCs`pkdCpLFq;Q%t$dte&5tTLVq4}_&oNZGuF>+-x>dCYst-?22GlWxs1fAUBf z`|S4(?-%04_E^x!@T4k)Ncy<7GjD`}5M> z$=e`4i}wK2;x&KJ4PO+d??#SnOV&}+FVfOW1tj+Ea@J~x7RKX_JBGFsof>PLF76Oq>IxwE%;|eedp+f_r5a7)Un}Q6b`h+k<~KL zG;X#sGy?pY7J}ZQcWHSS-@t{ouFz(C<66+;v}*3-RrNV5gNMOY#W8FYf?860krN zQ9j@sUGcjVwG35K&B>+6&OG0!tSYdUky?Duebh$f#A>6|H51eVjaC^CflzjSM&I}V zYIr)U@M=Et{?z2x1;VVVE|RgdzvGLZ&Z7%^xpfVG*|{d##(_1=;gf9XxM_KD5?%d6 zC?6cncl_$b8_-5hvLt?z7Y#U_c6<*8vDsE1B>he`<$gfaX6q~eJPHXJ{T)@00Z}WS zL9mDlnT?9nY$~SN_66>0m*ttmLQ7V1#oNRdR~-TO&WX=!{c`9%3rN<}LTY`1R`Iv? zENPu~sUN4`R@llX@m83Nt)V&}`#;|IDiW0q9*a^Ka~<+@Qu#S)Z*9EYHyR71?eEoQ z0n0v?{suBo0+8XdP8rSjT-0{JdofJyaoqcI*^7vS5vW9d+}m^3xIwq5p{(;ZnL!R6vCX5^_d>1VVpd?EQF z9zD0l@+P9}u9%^uJ0(Hzc`RV9)Ns#pT>IMUM=q@Bo#0*~_>7xXY2D_iSvh&`5nVaz z2DmgQONr6;h_K06ApaIuG{m&+OGEJVtOo55u|@;y(z^3CB56q4hzc~<3{L`W#$5K| zy-k@=-Je>Mz2yb5izHN+EzNj-Jzv$-KVgK^9r3kke0~oA)o)amfHiKm-Ig?N-I*v} znIgigM%4WosHdOLe&%x!FTSdm#le>A!ayfmui-gUqs|{9N6mdD+(agoyU;RxZB@R$ zM04}Xo%iz9vsb4=$V)821lGOAs2rtPxlZ>UKKAaxN%Cb)*+#qH94?&)K+=73$sn&l zhll8v4_a&U*ua(&r&)@V@8&Jw+~v}|hqQmPrbNnHCCJ^O-ss`c$|-U~2I(TU!Fm*N zK4A`S;9~Y`0mx^@WxUr2b4O%bB|E}^IRkN1joB)?0v!u2A69cZ@RRL<+;K`--!^>F zM?m7-#^3fLJ`uR!ji`ysby0sDem9jUMf0XE7V(1oWy>~2R z=FSamAejuYmNz+lXIy$z(Q3v)qqT1R1)TG>OQ!f6-nsu-q!Y$As6(xgGY`N&I44(u z9i-8(4db+fMw>JXS_(-1rlQan6+ViH?4WBegEd!3A^Q*5c++iR7JSRCsnA`3cgAE48XnL)-H zVFqn7x0D0!yX$hzUSY#2>% z&^JkPA$gO%3e6K7JPDwdS(=*csoPSVlZptbGNVK~1+ z)e81l@6=W5(glWjG*8koN)ixDAU1F1I^@bl=#-x;ymI` zIgbNoR)M3um{Q?1fUcJhm?b-9wtvk{lC@MzfCIB#YL>6($!K#*ZAT{SFq@v%2O`D9 zE07mTX6B%r=2tG$i{X;9zze^Hv|kZ8DtG{W`{s3p?x}HF=eTyk+OazhP4ciK6J7qV zq8k*-SbqX@I4`8mVmdCM)3d9|6)n9#}!ZmzcP zs8uA5o!zLWKdrI@ojA}fj_bdA6!1y)6kdK3_3Ypa04iFhuu!58?wg_Y2L6=$RQ-&^ z93#L7F>}i=w!ZKscw)DJ$+OHzcWo{&x!Nl;^=kobB2oun z`3vwDY5(P%UZyg8Xz{4Ay;O6@IW8_P%iGW}qttlfHwT?$Yi&g#uYH5z`i{NS+Oc!g z=7FA_Yf^@J=P`ERsC!!nS5UYBgyeyz=jAR8+Cx%;UhG$E0Qu%Xj5sp}Gz@yJ7}OWf z$trJ#osSn#l$}f}U)d&_lSj--_!xdU-aZ4o?D6@EVgU&58(`q~{-dZxosf|a*U611bg>-aFKEMr3 zWnHQetUt*eF~V4Z?pE=y=*gY`jQueB;9VFk|At@w?Iio~1Kq*M7*^B$8`1fT%Si+2 zuafqY{6q51ArWBIbR;wJ{nMl62cp9UP4}l176sC8JDrmLiR=%+rwUriHFHZv+pRxp zr-s%<2%k=4E9Ei*^@Cip+nxPIc*a4iibeSs4Wn5NLH0GsrfDmPx}j@~;}1aQFAC?7 zOz;0r_;PToUz@)Ekr4&gN9w{R_UOrfLp1+)>-&E?K!J7r$LFVuUrFz`CNG}<;|z;! zhLOf3VRrnB1_|c9zTA3u=|@k-BLAa2A4}*j52Y4-r2Kg9;;EUgVZ428!vDihg&3Gh zWK>i~g6zZxY$4rjdzAz5xs36=FqE4}f7jqEyixsQ0e(;H5C|CbBr0xLnw_x*n}V1MtW3KlRo z`0Umhn8DXSF|Qbbzc93vLtBDBmZE^*2j@j+dQ)TjCpnh#v6D=4dcFSCK7D{*P1)n4 zJ^vtDAkc=y0*vXQ2oHa1UsyhHGCwwYSkXV&v6#@0y+pi^4??0ScECIh}}i4MH~MFxut%Y3i+rt9~=020wwng9R* literal 0 HcmV?d00001 diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab.html new file mode 100644 index 00000000000..9b358d2d6ea --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab.html @@ -0,0 +1,879 @@ + + + + + + + + + + + + airflow.providers.fab — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+# NOTE! THIS FILE IS AUTOMATICALLY GENERATED AND WILL BE
+# OVERWRITTEN WHEN PREPARING DOCUMENTATION FOR THE PACKAGES.
+#
+# IF YOU WANT TO MODIFY THIS FILE, YOU SHOULD MODIFY THE TEMPLATE
+# `PROVIDER__INIT__PY_TEMPLATE.py.jinja2` IN the `dev/breeze/src/airflow_breeze/templates` DIRECTORY
+#
+from __future__ import annotations
+
+import packaging.version
+
+__all__ = ["__version__"]
+
+
[docs]__version__ = "1.0.4"
+ +try: + from airflow import __version__ as airflow_version +except ImportError: + from airflow.version import version as airflow_version + +if packaging.version.parse(packaging.version.parse(airflow_version).base_version) < packaging.version.parse( + "2.9.0" +): + raise RuntimeError( + f"The package `apache-airflow-providers-fab:{__version__}` needs Apache Airflow 2.9.0+" + ) +
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/api/auth/backend/basic_auth.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/api/auth/backend/basic_auth.html new file mode 100644 index 00000000000..7a3901f2fd0 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/api/auth/backend/basic_auth.html @@ -0,0 +1,909 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.api.auth.backend.basic_auth — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.api.auth.backend.basic_auth

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""Basic authentication backend."""
+
+from __future__ import annotations
+
+from functools import wraps
+from typing import TYPE_CHECKING, Any, Callable, TypeVar, cast
+
+from flask import Response, request
+from flask_appbuilder.const import AUTH_LDAP
+from flask_login import login_user
+
+from airflow.providers.fab.auth_manager.security_manager.override import FabAirflowSecurityManagerOverride
+from airflow.www.extensions.init_auth_manager import get_auth_manager
+
+if TYPE_CHECKING:
+    from airflow.providers.fab.auth_manager.models import User
+
+
[docs]CLIENT_AUTH: tuple[str, str] | Any | None = None
+ +
[docs]T = TypeVar("T", bound=Callable)
+ + +
[docs]def init_app(_): + """Initialize authentication backend."""
+ + +
[docs]def auth_current_user() -> User | None: + """Authenticate and set current user if Authorization header exists.""" + auth = request.authorization + if auth is None or not auth.username or not auth.password: + return None + + security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager) + user = None + if security_manager.auth_type == AUTH_LDAP: + user = security_manager.auth_user_ldap(auth.username, auth.password) + if user is None: + user = security_manager.auth_user_db(auth.username, auth.password) + if user is not None: + login_user(user, remember=False) + return user
+ + +
[docs]def requires_authentication(function: T): + """Decorate functions that require authentication.""" + + @wraps(function) + def decorated(*args, **kwargs): + if auth_current_user() is not None: + return function(*args, **kwargs) + else: + return Response("Unauthorized", 401, {"WWW-Authenticate": "Basic"}) + + return cast(T, decorated)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/api/auth/backend/kerberos_auth.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/api/auth/backend/kerberos_auth.html new file mode 100644 index 00000000000..280f9688aa5 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/api/auth/backend/kerberos_auth.html @@ -0,0 +1,883 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import logging
+from functools import partial
+from typing import Any, cast
+
+from requests_kerberos import HTTPKerberosAuth
+
+from airflow.api.auth.backend.kerberos_auth import (
+    init_app as base_init_app,
+    requires_authentication as base_requires_authentication,
+)
+from airflow.providers.fab.auth_manager.security_manager.override import FabAirflowSecurityManagerOverride
+from airflow.www.extensions.init_auth_manager import get_auth_manager
+
+
[docs]log = logging.getLogger(__name__)
+ +
[docs]CLIENT_AUTH: tuple[str, str] | Any | None = HTTPKerberosAuth(service="airflow")
+ + +
[docs]def find_user(username=None, email=None): + security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager) + return security_manager.find_user(username=username, email=email)
+ + +
[docs]init_app = base_init_app
+
[docs]requires_authentication = partial(base_requires_authentication, find_user=find_user)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/api_endpoints/role_and_permission_endpoint.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/api_endpoints/role_and_permission_endpoint.html new file mode 100644 index 00000000000..9423c0bf36f --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/api_endpoints/role_and_permission_endpoint.html @@ -0,0 +1,1009 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from http import HTTPStatus
+from typing import TYPE_CHECKING, cast
+
+from connexion import NoContent
+from flask import request
+from marshmallow import ValidationError
+from sqlalchemy import asc, desc, func, select
+
+from airflow.api_connexion.exceptions import AlreadyExists, BadRequest, NotFound
+from airflow.api_connexion.parameters import check_limit, format_parameters
+from airflow.api_connexion.schemas.role_and_permission_schema import (
+    ActionCollection,
+    RoleCollection,
+    action_collection_schema,
+    role_collection_schema,
+    role_schema,
+)
+from airflow.api_connexion.security import requires_access_custom_view
+from airflow.providers.fab.auth_manager.models import Action, Role
+from airflow.providers.fab.auth_manager.security_manager.override import FabAirflowSecurityManagerOverride
+from airflow.security import permissions
+from airflow.www.extensions.init_auth_manager import get_auth_manager
+
+if TYPE_CHECKING:
+    from airflow.api_connexion.types import APIResponse, UpdateMask
+
+
+def _check_action_and_resource(sm: FabAirflowSecurityManagerOverride, perms: list[tuple[str, str]]) -> None:
+    """
+    Check if the action or resource exists and otherwise raise 400.
+
+    This function is intended for use in the REST API because it raises an HTTP error 400
+    """
+    for action, resource in perms:
+        if not sm.get_action(action):
+            raise BadRequest(detail=f"The specified action: {action!r} was not found")
+        if not sm.get_resource(resource):
+            raise BadRequest(detail=f"The specified resource: {resource!r} was not found")
+
+
+@requires_access_custom_view("GET", permissions.RESOURCE_ROLE)
+
[docs]def get_role(*, role_name: str) -> APIResponse: + """Get role.""" + security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager) + role = security_manager.find_role(name=role_name) + if not role: + raise NotFound(title="Role not found", detail=f"Role with name {role_name!r} was not found") + return role_schema.dump(role)
+ + +@requires_access_custom_view("GET", permissions.RESOURCE_ROLE) +@format_parameters({"limit": check_limit}) +
[docs]def get_roles(*, order_by: str = "name", limit: int, offset: int | None = None) -> APIResponse: + """Get roles.""" + security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager) + session = security_manager.get_session + total_entries = session.scalars(select(func.count(Role.id))).one() + direction = desc if order_by.startswith("-") else asc + to_replace = {"role_id": "id"} + order_param = order_by.strip("-") + order_param = to_replace.get(order_param, order_param) + allowed_sort_attrs = ["role_id", "name"] + if order_by not in allowed_sort_attrs: + raise BadRequest( + detail=f"Ordering with '{order_by}' is disallowed or " + f"the attribute does not exist on the model" + ) + + query = select(Role) + roles = ( + session.scalars(query.order_by(direction(getattr(Role, order_param))).offset(offset).limit(limit)) + .unique() + .all() + ) + + return role_collection_schema.dump(RoleCollection(roles=roles, total_entries=total_entries))
+ + +@requires_access_custom_view("GET", permissions.RESOURCE_ACTION) +@format_parameters({"limit": check_limit}) +
[docs]def get_permissions(*, limit: int, offset: int | None = None) -> APIResponse: + """Get permissions.""" + security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager) + session = security_manager.get_session + total_entries = session.scalars(select(func.count(Action.id))).one() + query = select(Action) + actions = session.scalars(query.offset(offset).limit(limit)).all() + return action_collection_schema.dump(ActionCollection(actions=actions, total_entries=total_entries))
+ + +@requires_access_custom_view("DELETE", permissions.RESOURCE_ROLE) +
[docs]def delete_role(*, role_name: str) -> APIResponse: + """Delete a role.""" + security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager) + + role = security_manager.find_role(name=role_name) + if not role: + raise NotFound(title="Role not found", detail=f"Role with name {role_name!r} was not found") + security_manager.delete_role(role_name=role_name) + return NoContent, HTTPStatus.NO_CONTENT
+ + +@requires_access_custom_view("PUT", permissions.RESOURCE_ROLE) +
[docs]def patch_role(*, role_name: str, update_mask: UpdateMask = None) -> APIResponse: + """Update a role.""" + security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager) + body = request.json + try: + data = role_schema.load(body) + except ValidationError as err: + raise BadRequest(detail=str(err.messages)) + role = security_manager.find_role(name=role_name) + if not role: + raise NotFound(title="Role not found", detail=f"Role with name {role_name!r} was not found") + if update_mask: + update_mask = [i.strip() for i in update_mask] + data_ = {} + for field in update_mask: + if field in data and field != "permissions": + data_[field] = data[field] + elif field == "actions": + data_["permissions"] = data["permissions"] + else: + raise BadRequest(detail=f"'{field}' in update_mask is unknown") + data = data_ + if "permissions" in data: + perms = [(item["action"]["name"], item["resource"]["name"]) for item in data["permissions"] if item] + _check_action_and_resource(security_manager, perms) + security_manager.bulk_sync_roles([{"role": role_name, "perms": perms}]) + new_name = data.get("name") + if new_name is not None and new_name != role.name: + security_manager.update_role(role_id=role.id, name=new_name) + return role_schema.dump(role)
+ + +@requires_access_custom_view("POST", permissions.RESOURCE_ROLE) +
[docs]def post_role() -> APIResponse: + """Create a new role.""" + security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager) + body = request.json + try: + data = role_schema.load(body) + except ValidationError as err: + raise BadRequest(detail=str(err.messages)) + role = security_manager.find_role(name=data["name"]) + if not role: + perms = [(item["action"]["name"], item["resource"]["name"]) for item in data["permissions"] if item] + _check_action_and_resource(security_manager, perms) + security_manager.bulk_sync_roles([{"role": data["name"], "perms": perms}]) + return role_schema.dump(role) + detail = f"Role with name {role.name!r} already exists; please update with the PATCH endpoint" + raise AlreadyExists(detail=detail)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/api_endpoints/user_endpoint.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/api_endpoints/user_endpoint.html new file mode 100644 index 00000000000..6cb01a1a2d4 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/api_endpoints/user_endpoint.html @@ -0,0 +1,1054 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.api_endpoints.user_endpoint — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.api_endpoints.user_endpoint

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from http import HTTPStatus
+from typing import TYPE_CHECKING, cast
+
+from connexion import NoContent
+from flask import request
+from marshmallow import ValidationError
+from sqlalchemy import asc, desc, func, select
+from werkzeug.security import generate_password_hash
+
+from airflow.api_connexion.exceptions import AlreadyExists, BadRequest, NotFound, Unknown
+from airflow.api_connexion.parameters import check_limit, format_parameters
+from airflow.api_connexion.schemas.user_schema import (
+    UserCollection,
+    user_collection_item_schema,
+    user_collection_schema,
+    user_schema,
+)
+from airflow.api_connexion.security import requires_access_custom_view
+from airflow.providers.fab.auth_manager.models import User
+from airflow.providers.fab.auth_manager.security_manager.override import FabAirflowSecurityManagerOverride
+from airflow.security import permissions
+from airflow.www.extensions.init_auth_manager import get_auth_manager
+
+if TYPE_CHECKING:
+    from airflow.api_connexion.types import APIResponse, UpdateMask
+    from airflow.providers.fab.auth_manager.models import Role
+
+
+@requires_access_custom_view("GET", permissions.RESOURCE_USER)
+
[docs]def get_user(*, username: str) -> APIResponse: + """Get a user.""" + security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager) + user = security_manager.find_user(username=username) + if not user: + raise NotFound(title="User not found", detail=f"The User with username `{username}` was not found") + return user_collection_item_schema.dump(user)
+ + +@requires_access_custom_view("GET", permissions.RESOURCE_USER) +@format_parameters({"limit": check_limit}) +
[docs]def get_users(*, limit: int, order_by: str = "id", offset: str | None = None) -> APIResponse: + """Get users.""" + security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager) + session = security_manager.get_session + total_entries = session.execute(select(func.count(User.id))).scalar() + direction = desc if order_by.startswith("-") else asc + to_replace = {"user_id": "id"} + order_param = order_by.strip("-") + order_param = to_replace.get(order_param, order_param) + allowed_sort_attrs = [ + "id", + "first_name", + "last_name", + "user_name", + "email", + "is_active", + "role", + ] + if order_by not in allowed_sort_attrs: + raise BadRequest( + detail=f"Ordering with '{order_by}' is disallowed or " + f"the attribute does not exist on the model" + ) + + query = select(User).order_by(direction(getattr(User, order_param))).offset(offset).limit(limit) + users = session.scalars(query).all() + + return user_collection_schema.dump(UserCollection(users=users, total_entries=total_entries))
+ + +@requires_access_custom_view("POST", permissions.RESOURCE_USER) +
[docs]def post_user() -> APIResponse: + """Create a new user.""" + try: + data = user_schema.load(request.json) + except ValidationError as e: + raise BadRequest(detail=str(e.messages)) + + security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager) + username = data["username"] + email = data["email"] + + if security_manager.find_user(username=username): + detail = f"Username `{username}` already exists. Use PATCH to update." + raise AlreadyExists(detail=detail) + if security_manager.find_user(email=email): + detail = f"The email `{email}` is already taken." + raise AlreadyExists(detail=detail) + + roles_to_add = [] + missing_role_names = [] + for role_data in data.pop("roles", ()): + role_name = role_data["name"] + role = security_manager.find_role(role_name) + if role is None: + missing_role_names.append(role_name) + else: + roles_to_add.append(role) + if missing_role_names: + detail = f"Unknown roles: {', '.join(repr(n) for n in missing_role_names)}" + raise BadRequest(detail=detail) + + if not roles_to_add: # No roles provided, use the F.A.B's default registered user role. + roles_to_add.append(security_manager.find_role(security_manager.auth_user_registration_role)) + + user = security_manager.add_user(role=roles_to_add, **data) + if not user: + detail = f"Failed to add user `{username}`." + raise Unknown(detail=detail) + + return user_schema.dump(user)
+ + +@requires_access_custom_view("PUT", permissions.RESOURCE_USER) +
[docs]def patch_user(*, username: str, update_mask: UpdateMask = None) -> APIResponse: + """Update a user.""" + try: + data = user_schema.load(request.json) + except ValidationError as e: + raise BadRequest(detail=str(e.messages)) + + security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager) + + user = security_manager.find_user(username=username) + if user is None: + detail = f"The User with username `{username}` was not found" + raise NotFound(title="User not found", detail=detail) + # Check unique username + new_username = data.get("username") + if new_username and new_username != username: + if security_manager.find_user(username=new_username): + raise AlreadyExists(detail=f"The username `{new_username}` already exists") + + # Check unique email + email = data.get("email") + if email and email != user.email: + if security_manager.find_user(email=email): + raise AlreadyExists(detail=f"The email `{email}` already exists") + + # Get fields to update. + if update_mask is not None: + masked_data = {} + missing_mask_names = [] + for field in update_mask: + field = field.strip() + try: + masked_data[field] = data[field] + except KeyError: + missing_mask_names.append(field) + if missing_mask_names: + detail = f"Unknown update masks: {', '.join(repr(n) for n in missing_mask_names)}" + raise BadRequest(detail=detail) + data = masked_data + + roles_to_update: list[Role] | None + if "roles" in data: + roles_to_update = [] + missing_role_names = [] + for role_data in data.pop("roles", ()): + role_name = role_data["name"] + role = security_manager.find_role(role_name) + if role is None: + missing_role_names.append(role_name) + else: + roles_to_update.append(role) + if missing_role_names: + detail = f"Unknown roles: {', '.join(repr(n) for n in missing_role_names)}" + raise BadRequest(detail=detail) + else: + roles_to_update = None # Don't change existing value. + + if "password" in data: + user.password = generate_password_hash(data.pop("password")) + if roles_to_update is not None: + user.roles = roles_to_update + for key, value in data.items(): + setattr(user, key, value) + security_manager.update_user(user) + + return user_schema.dump(user)
+ + +@requires_access_custom_view("DELETE", permissions.RESOURCE_USER) +
[docs]def delete_user(*, username: str) -> APIResponse: + """Delete a user.""" + security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager) + + user = security_manager.find_user(username=username) + if user is None: + detail = f"The User with username `{username}` was not found" + raise NotFound(title="User not found", detail=detail) + + user.roles = [] # Clear foreign keys on this user first. + security_manager.get_session.delete(user) + security_manager.get_session.commit() + + return NoContent, HTTPStatus.NO_CONTENT
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/definition.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/definition.html new file mode 100644 index 00000000000..4f763c58b1f --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/definition.html @@ -0,0 +1,1084 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.cli_commands.definition — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.cli_commands.definition

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import textwrap
+
+from airflow.cli.cli_config import (
+    ARG_OUTPUT,
+    ARG_VERBOSE,
+    ActionCommand,
+    Arg,
+    lazy_load_command,
+)
+
+############
+# # ARGS # #
+############
+
+# users
+
[docs]ARG_USERNAME = Arg(("-u", "--username"), help="Username of the user", required=True, type=str)
+
[docs]ARG_USERNAME_OPTIONAL = Arg(("-u", "--username"), help="Username of the user", type=str)
+
[docs]ARG_FIRSTNAME = Arg(("-f", "--firstname"), help="First name of the user", required=True, type=str)
+
[docs]ARG_LASTNAME = Arg(("-l", "--lastname"), help="Last name of the user", required=True, type=str)
+
[docs]ARG_ROLE = Arg( + ("-r", "--role"), + help="Role of the user. Existing roles include Admin, User, Op, Viewer, and Public", + required=True, + type=str, +)
+
[docs]ARG_EMAIL = Arg(("-e", "--email"), help="Email of the user", required=True, type=str)
+
[docs]ARG_EMAIL_OPTIONAL = Arg(("-e", "--email"), help="Email of the user", type=str)
+
[docs]ARG_PASSWORD = Arg( + ("-p", "--password"), + help="Password of the user, required to create a user without --use-random-password", + type=str, +)
+
[docs]ARG_USE_RANDOM_PASSWORD = Arg( + ("--use-random-password",), + help="Do not prompt for password. Use random string instead." + " Required to create a user without --password ", + default=False, + action="store_true", +)
+
[docs]ARG_USER_IMPORT = Arg( + ("import",), + metavar="FILEPATH", + help="Import users from JSON file. Example format::\n" + + textwrap.indent( + textwrap.dedent( + """ + [ + { + "email": "foo@bar.org", + "firstname": "Jon", + "lastname": "Doe", + "roles": ["Public"], + "username": "jondoe" + } + ]""" + ), + " " * 4, + ), +)
+
[docs]ARG_USER_EXPORT = Arg(("export",), metavar="FILEPATH", help="Export all users to JSON file")
+ +# roles +
[docs]ARG_CREATE_ROLE = Arg(("-c", "--create"), help="Create a new role", action="store_true")
+
[docs]ARG_LIST_ROLES = Arg(("-l", "--list"), help="List roles", action="store_true")
+
[docs]ARG_ROLES = Arg(("role",), help="The name of a role", nargs="*")
+
[docs]ARG_PERMISSIONS = Arg(("-p", "--permission"), help="Show role permissions", action="store_true")
+
[docs]ARG_ROLE_RESOURCE = Arg(("-r", "--resource"), help="The name of permissions", nargs="*", required=True)
+
[docs]ARG_ROLE_ACTION = Arg(("-a", "--action"), help="The action of permissions", nargs="*")
+
[docs]ARG_ROLE_ACTION_REQUIRED = Arg(("-a", "--action"), help="The action of permissions", nargs="*", required=True)
+ +
[docs]ARG_ROLE_IMPORT = Arg(("file",), help="Import roles from JSON file", nargs=None)
+
[docs]ARG_ROLE_EXPORT = Arg(("file",), help="Export all roles to JSON file", nargs=None)
+
[docs]ARG_ROLE_EXPORT_FMT = Arg( + ("-p", "--pretty"), + help="Format output JSON file by sorting role names and indenting by 4 spaces", + action="store_true", +)
+ +# sync-perm +
[docs]ARG_INCLUDE_DAGS = Arg( + ("--include-dags",), help="If passed, DAG specific permissions will also be synced.", action="store_true" +)
+ +################ +# # COMMANDS # # +################ + +
[docs]USERS_COMMANDS = ( + ActionCommand( + name="list", + help="List users", + func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.user_command.users_list"), + args=(ARG_OUTPUT, ARG_VERBOSE), + ), + ActionCommand( + name="create", + help="Create a user", + func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.user_command.users_create"), + args=( + ARG_ROLE, + ARG_USERNAME, + ARG_EMAIL, + ARG_FIRSTNAME, + ARG_LASTNAME, + ARG_PASSWORD, + ARG_USE_RANDOM_PASSWORD, + ARG_VERBOSE, + ), + epilog=( + "examples:\n" + 'To create an user with "Admin" role and username equals to "admin", run:\n' + "\n" + " $ airflow users create \\\n" + " --username admin \\\n" + " --firstname FIRST_NAME \\\n" + " --lastname LAST_NAME \\\n" + " --role Admin \\\n" + " --email admin@example.org" + ), + ), + ActionCommand( + name="reset-password", + help="Reset a user's password", + func=lazy_load_command( + "airflow.providers.fab.auth_manager.cli_commands.user_command.user_reset_password" + ), + args=( + ARG_USERNAME_OPTIONAL, + ARG_EMAIL_OPTIONAL, + ARG_PASSWORD, + ARG_USE_RANDOM_PASSWORD, + ARG_VERBOSE, + ), + epilog=( + "examples:\n" + 'To reset an user with username equals to "admin", run:\n' + "\n" + " $ airflow users reset-password \\\n" + " --username admin" + ), + ), + ActionCommand( + name="delete", + help="Delete a user", + func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.user_command.users_delete"), + args=(ARG_USERNAME_OPTIONAL, ARG_EMAIL_OPTIONAL, ARG_VERBOSE), + ), + ActionCommand( + name="add-role", + help="Add role to a user", + func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.user_command.add_role"), + args=(ARG_USERNAME_OPTIONAL, ARG_EMAIL_OPTIONAL, ARG_ROLE, ARG_VERBOSE), + ), + ActionCommand( + name="remove-role", + help="Remove role from a user", + func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.user_command.remove_role"), + args=(ARG_USERNAME_OPTIONAL, ARG_EMAIL_OPTIONAL, ARG_ROLE, ARG_VERBOSE), + ), + ActionCommand( + name="import", + help="Import users", + func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.user_command.users_import"), + args=(ARG_USER_IMPORT, ARG_VERBOSE), + ), + ActionCommand( + name="export", + help="Export all users", + func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.user_command.users_export"), + args=(ARG_USER_EXPORT, ARG_VERBOSE), + ), +)
+
[docs]ROLES_COMMANDS = ( + ActionCommand( + name="list", + help="List roles", + func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.role_command.roles_list"), + args=(ARG_PERMISSIONS, ARG_OUTPUT, ARG_VERBOSE), + ), + ActionCommand( + name="create", + help="Create role", + func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.role_command.roles_create"), + args=(ARG_ROLES, ARG_VERBOSE), + ), + ActionCommand( + name="delete", + help="Delete role", + func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.role_command.roles_delete"), + args=(ARG_ROLES, ARG_VERBOSE), + ), + ActionCommand( + name="add-perms", + help="Add roles permissions", + func=lazy_load_command( + "airflow.providers.fab.auth_manager.cli_commands.role_command.roles_add_perms" + ), + args=(ARG_ROLES, ARG_ROLE_RESOURCE, ARG_ROLE_ACTION_REQUIRED, ARG_VERBOSE), + ), + ActionCommand( + name="del-perms", + help="Delete roles permissions", + func=lazy_load_command( + "airflow.providers.fab.auth_manager.cli_commands.role_command.roles_del_perms" + ), + args=(ARG_ROLES, ARG_ROLE_RESOURCE, ARG_ROLE_ACTION, ARG_VERBOSE), + ), + ActionCommand( + name="export", + help="Export roles (without permissions) from db to JSON file", + func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.role_command.roles_export"), + args=(ARG_ROLE_EXPORT, ARG_ROLE_EXPORT_FMT, ARG_VERBOSE), + ), + ActionCommand( + name="import", + help="Import roles (without permissions) from JSON file to db", + func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.role_command.roles_import"), + args=(ARG_ROLE_IMPORT, ARG_VERBOSE), + ), +)
+ +
[docs]SYNC_PERM_COMMAND = ActionCommand( + name="sync-perm", + help="Update permissions for existing roles and optionally DAGs", + func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.sync_perm_command.sync_perm"), + args=(ARG_INCLUDE_DAGS, ARG_VERBOSE), +)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/role_command.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/role_command.html new file mode 100644 index 00000000000..e6d42a8df46 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/role_command.html @@ -0,0 +1,1071 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.cli_commands.role_command — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.cli_commands.role_command

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""Roles sub-commands."""
+
+from __future__ import annotations
+
+import itertools
+import json
+import os
+from argparse import Namespace
+from collections import defaultdict
+from typing import TYPE_CHECKING
+
+from airflow.cli.simple_table import AirflowConsole
+from airflow.providers.fab.auth_manager.cli_commands.utils import get_application_builder
+from airflow.providers.fab.auth_manager.security_manager.constants import EXISTING_ROLES
+from airflow.utils import cli as cli_utils
+from airflow.utils.cli import suppress_logs_and_warning
+from airflow.utils.providers_configuration_loader import providers_configuration_loaded
+
+if TYPE_CHECKING:
+    from airflow.providers.fab.auth_manager.models import Action, Permission, Resource, Role
+
+
+@suppress_logs_and_warning
+@providers_configuration_loaded
+
[docs]def roles_list(args): + """List all existing roles.""" + with get_application_builder() as appbuilder: + roles = appbuilder.sm.get_all_roles() + + if not args.permission: + AirflowConsole().print_as( + data=sorted(r.name for r in roles), output=args.output, mapper=lambda x: {"name": x} + ) + return + + permission_map: dict[tuple[str, str], list[str]] = defaultdict(list) + for role in roles: + for permission in role.permissions: + permission_map[(role.name, permission.resource.name)].append(permission.action.name) + + AirflowConsole().print_as( + data=sorted(permission_map), + output=args.output, + mapper=lambda x: {"name": x[0], "resource": x[1], "action": ",".join(sorted(permission_map[x]))}, + )
+ + +@cli_utils.action_cli +@suppress_logs_and_warning +@providers_configuration_loaded +
[docs]def roles_create(args): + """Create new empty role in DB.""" + with get_application_builder() as appbuilder: + for role_name in args.role: + appbuilder.sm.add_role(role_name) + print(f"Added {len(args.role)} role(s)")
+ + +@cli_utils.action_cli +@suppress_logs_and_warning +@providers_configuration_loaded +
[docs]def roles_delete(args): + """Delete role in DB.""" + with get_application_builder() as appbuilder: + for role_name in args.role: + role = appbuilder.sm.find_role(role_name) + if not role: + print(f"Role named '{role_name}' does not exist") + exit(1) + for role_name in args.role: + appbuilder.sm.delete_role(role_name) + print(f"Deleted {len(args.role)} role(s)")
+ + +def __roles_add_or_remove_permissions(args): + with get_application_builder() as appbuilder: + is_add: bool = args.subcommand.startswith("add") + + role_map = {} + perm_map: dict[tuple[str, str], set[str]] = defaultdict(set) + asm = appbuilder.sm + for name in args.role: + role: Role | None = asm.find_role(name) + if not role: + print(f"Role named '{name}' does not exist") + exit(1) + + role_map[name] = role + for permission in role.permissions: + perm_map[(name, permission.resource.name)].add(permission.action.name) + + for name in args.resource: + resource: Resource | None = asm.get_resource(name) + if not resource: + print(f"Resource named '{name}' does not exist") + exit(1) + + for name in args.action or []: + action: Action | None = asm.get_action(name) + if not action: + print(f"Action named '{name}' does not exist") + exit(1) + + permission_count = 0 + for role_name, resource_name, action_name in itertools.product( + args.role, args.resource, args.action or [None] + ): + res_key = (role_name, resource_name) + if is_add and action_name not in perm_map[res_key]: + perm: Permission | None = asm.create_permission(action_name, resource_name) + asm.add_permission_to_role(role_map[role_name], perm) + print(f"Added {perm} to role {role_name}") + permission_count += 1 + elif not is_add and res_key in perm_map: + for _action_name in perm_map[res_key] if action_name is None else [action_name]: + perm: Permission | None = asm.get_permission(_action_name, resource_name) + asm.remove_permission_from_role(role_map[role_name], perm) + print(f"Deleted {perm} from role {role_name}") + permission_count += 1 + + print(f"{'Added' if is_add else 'Deleted'} {permission_count} permission(s)") + + +@cli_utils.action_cli +@suppress_logs_and_warning +@providers_configuration_loaded +
[docs]def roles_add_perms(args): + """Add permissions to role in DB.""" + __roles_add_or_remove_permissions(args)
+ + +@cli_utils.action_cli +@suppress_logs_and_warning +@providers_configuration_loaded +
[docs]def roles_del_perms(args): + """Delete permissions from role in DB.""" + __roles_add_or_remove_permissions(args)
+ + +@suppress_logs_and_warning +@providers_configuration_loaded +
[docs]def roles_export(args): + """Export all the roles from the database to a file including permissions.""" + with get_application_builder() as appbuilder: + roles = appbuilder.sm.get_all_roles() + exporting_roles = [role for role in roles if role.name not in EXISTING_ROLES] + filename = os.path.expanduser(args.file) + + permission_map: dict[tuple[str, str], list[str]] = defaultdict(list) + for role in exporting_roles: + if role.permissions: + for permission in role.permissions: + permission_map[(role.name, permission.resource.name)].append(permission.action.name) + else: + permission_map[(role.name, "")].append("") + export_data = [ + {"name": role, "resource": resource, "action": ",".join(sorted(permissions))} + for (role, resource), permissions in permission_map.items() + ] + kwargs = {} if not args.pretty else {"sort_keys": False, "indent": 4} + with open(filename, "w", encoding="utf-8") as f: + json.dump(export_data, f, **kwargs) + print( + f"{len(exporting_roles)} roles with {len(export_data)} linked permissions successfully exported to {filename}" + )
+ + +@cli_utils.action_cli +@suppress_logs_and_warning +
[docs]def roles_import(args): + """ + Import all the roles into the db from the given json file including their permissions. + + Note, if a role already exists in the db, it is not overwritten, even when the permissions change. + """ + json_file = args.file + try: + with open(json_file) as f: + role_list = json.load(f) + except FileNotFoundError: + print(f"File '{json_file}' does not exist") + exit(1) + except ValueError as e: + print(f"File '{json_file}' is not a valid JSON file. Error: {e}") + exit(1) + + with get_application_builder() as appbuilder: + existing_roles = [role.name for role in appbuilder.sm.get_all_roles()] + roles_to_import = [role_dict for role_dict in role_list if role_dict["name"] not in existing_roles] + for role_dict in roles_to_import: + if role_dict["name"] not in appbuilder.sm.get_all_roles(): + if role_dict["action"] == "" or role_dict["resource"] == "": + appbuilder.sm.add_role(role_dict["name"]) + else: + appbuilder.sm.add_role(role_dict["name"]) + role_args = Namespace( + subcommand="add-perms", + role=[role_dict["name"]], + resource=[role_dict["resource"]], + action=role_dict["action"].split(","), + ) + __roles_add_or_remove_permissions(role_args) + + if role_dict["name"] in appbuilder.sm.get_all_roles(): + if role_dict["action"] == "" or role_dict["resource"] == "": + pass + else: + role_args = Namespace( + subcommand="add-perms", + role=[role_dict["name"]], + resource=[role_dict["resource"]], + action=role_dict["action"].split(","), + ) + __roles_add_or_remove_permissions(role_args) + print("roles and permissions successfully imported")
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/sync_perm_command.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/sync_perm_command.html new file mode 100644 index 00000000000..665f72b6def --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/sync_perm_command.html @@ -0,0 +1,878 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.cli_commands.sync_perm_command — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.cli_commands.sync_perm_command

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""Sync permission command."""
+
+from __future__ import annotations
+
+from airflow.utils import cli as cli_utils
+from airflow.utils.providers_configuration_loader import providers_configuration_loaded
+
+
+@cli_utils.action_cli
+@providers_configuration_loaded
+
[docs]def sync_perm(args): + """Update permissions for existing roles and DAGs.""" + from airflow.providers.fab.auth_manager.cli_commands.utils import get_application_builder + + with get_application_builder() as appbuilder: + print("Updating actions and resources for all existing roles") + # Add missing permissions for all the Base Views _before_ syncing/creating roles + appbuilder.add_permissions(update_perms=True) + appbuilder.sm.sync_roles() + if args.include_dags: + print("Updating permission on all DAG views") + appbuilder.sm.create_dag_specific_permissions()
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/user_command.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/user_command.html new file mode 100644 index 00000000000..763879b4e67 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/user_command.html @@ -0,0 +1,1118 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.cli_commands.user_command — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.cli_commands.user_command

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""User sub-commands."""
+
+from __future__ import annotations
+
+import functools
+import getpass
+import json
+import os
+import random
+import string
+from typing import Any
+
+import re2
+from marshmallow import Schema, fields, validate
+from marshmallow.exceptions import ValidationError
+
+from airflow.cli.simple_table import AirflowConsole
+from airflow.cli.utils import print_export_output
+from airflow.providers.fab.auth_manager.cli_commands.utils import get_application_builder
+from airflow.utils import cli as cli_utils
+from airflow.utils.cli import suppress_logs_and_warning
+from airflow.utils.providers_configuration_loader import providers_configuration_loaded
+
+
+
[docs]class UserSchema(Schema): + """user collection item schema.""" + +
[docs] id = fields.Int()
+
[docs] firstname = fields.Str(required=True)
+
[docs] lastname = fields.Str(required=True)
+
[docs] username = fields.Str(required=True)
+
[docs] email = fields.Email(required=True)
+
[docs] roles = fields.List(fields.Str, required=True, validate=validate.Length(min=1))
+ + +@suppress_logs_and_warning +@providers_configuration_loaded +
[docs]def users_list(args): + """List users at the command line.""" + with get_application_builder() as appbuilder: + users = appbuilder.sm.get_all_users() + fields = ["id", "username", "email", "first_name", "last_name", "roles"] + + AirflowConsole().print_as( + data=users, output=args.output, mapper=lambda x: {f: x.__getattribute__(f) for f in fields} + )
+ + +@cli_utils.action_cli(check_db=True) +@providers_configuration_loaded +
[docs]def users_create(args): + """Create new user in the DB.""" + with get_application_builder() as appbuilder: + role = appbuilder.sm.find_role(args.role) + if not role: + valid_roles = appbuilder.sm.get_all_roles() + raise SystemExit(f"{args.role} is not a valid role. Valid roles are: {valid_roles}") + password = _create_password(args) + if appbuilder.sm.find_user(args.username): + print(f"{args.username} already exist in the db") + return + user = appbuilder.sm.add_user( + args.username, args.firstname, args.lastname, args.email, role, password + ) + if user: + print(f'User "{args.username}" created with role "{args.role}"') + else: + raise SystemExit("Failed to create user")
+ + +def _find_user(args): + if not args.username and not args.email: + raise SystemExit("Missing args: must supply one of --username or --email") + + if args.username and args.email: + raise SystemExit("Conflicting args: must supply either --username or --email, but not both") + + with get_application_builder() as appbuilder: + user = appbuilder.sm.find_user(username=args.username, email=args.email) + if not user: + raise SystemExit(f'User "{args.username or args.email}" does not exist') + return user + + +@cli_utils.action_cli +@providers_configuration_loaded +
[docs]def user_reset_password(args): + """Reset user password user from DB.""" + user = _find_user(args) + password = _create_password(args) + with get_application_builder() as appbuilder: + if appbuilder.sm.reset_password(user.id, password): + print(f'User "{user.username}" password reset successfully') + else: + raise SystemExit("Failed to reset user password")
+ + +def _create_password(args): + if args.use_random_password: + password = "".join(random.choices(string.printable, k=16)) + elif args.password: + password = args.password + else: + password = getpass.getpass("Password:") + password_confirmation = getpass.getpass("Repeat for confirmation:") + if password != password_confirmation: + raise SystemExit("Passwords did not match") + return password + + +@cli_utils.action_cli +@providers_configuration_loaded +
[docs]def users_delete(args): + """Delete user from DB.""" + user = _find_user(args) + + # Clear the associated user roles first. + user.roles.clear() + + with get_application_builder() as appbuilder: + if appbuilder.sm.del_register_user(user): + print(f'User "{user.username}" deleted') + else: + raise SystemExit("Failed to delete user")
+ + +@cli_utils.action_cli +@providers_configuration_loaded +
[docs]def users_manage_role(args, remove=False): + """Delete or appends user roles.""" + user = _find_user(args) + + with get_application_builder() as appbuilder: + role = appbuilder.sm.find_role(args.role) + if not role: + valid_roles = appbuilder.sm.get_all_roles() + raise SystemExit(f'"{args.role}" is not a valid role. Valid roles are: {valid_roles}') + + if remove: + if role not in user.roles: + raise SystemExit(f'User "{user.username}" is not a member of role "{args.role}"') + + user.roles = [r for r in user.roles if r != role] + appbuilder.sm.update_user(user) + print(f'User "{user.username}" removed from role "{args.role}"') + else: + if role in user.roles: + raise SystemExit(f'User "{user.username}" is already a member of role "{args.role}"') + + user.roles.append(role) + appbuilder.sm.update_user(user) + print(f'User "{user.username}" added to role "{args.role}"')
+ + +@providers_configuration_loaded +
[docs]def users_export(args): + """Export all users to the json file.""" + with get_application_builder() as appbuilder: + users = appbuilder.sm.get_all_users() + fields = ["id", "username", "email", "first_name", "last_name", "roles"] + + # In the User model the first and last name fields have underscores, + # but the corresponding parameters in the CLI don't + def remove_underscores(s): + return re2.sub("_", "", s) + + users = [ + { + remove_underscores(field): user.__getattribute__(field) + if field != "roles" + else [r.name for r in user.roles] + for field in fields + } + for user in users + ] + + with open(args.export, "w") as file: + file.write(json.dumps(users, sort_keys=True, indent=4)) + print_export_output("users", users, file)
+ + +@cli_utils.action_cli +@providers_configuration_loaded +
[docs]def users_import(args): + """Import users from the json file.""" + json_file = getattr(args, "import") + if not os.path.exists(json_file): + raise SystemExit(f"File '{json_file}' does not exist") + + users_list = None + try: + with open(json_file) as file: + users_list = json.loads(file.read()) + except ValueError as e: + raise SystemExit(f"File '{json_file}' is not valid JSON. Error: {e}") + + users_created, users_updated = _import_users(users_list) + if users_created: + print("Created the following users:\n\t{}".format("\n\t".join(users_created))) + + if users_updated: + print("Updated the following users:\n\t{}".format("\n\t".join(users_updated)))
+ + +def _import_users(users_list: list[dict[str, Any]]): + with get_application_builder() as appbuilder: + users_created = [] + users_updated = [] + + try: + UserSchema(many=True).load(users_list) + except ValidationError as e: + msg = [] + for row_num, failure in e.normalized_messages().items(): + msg.append(f"[Item {row_num}]") + for key, value in failure.items(): + msg.append(f"\t{key}: {value}") + raise SystemExit( + "Error: Input file didn't pass validation. See below:\n{}".format("\n".join(msg)) + ) + + for user in users_list: + roles = [] + for rolename in user["roles"]: + role = appbuilder.sm.find_role(rolename) + if not role: + valid_roles = appbuilder.sm.get_all_roles() + raise SystemExit( + f'Error: "{rolename}" is not a valid role. Valid roles are: {valid_roles}' + ) + roles.append(role) + + existing_user = appbuilder.sm.find_user(email=user["email"]) + if existing_user: + print(f"Found existing user with email '{user['email']}'") + if existing_user.username != user["username"]: + raise SystemExit( + f"Error: Changing the username is not allowed - " + f"please delete and recreate the user with email {user['email']!r}" + ) + + existing_user.roles = roles + existing_user.first_name = user["firstname"] + existing_user.last_name = user["lastname"] + appbuilder.sm.update_user(existing_user) + users_updated.append(user["email"]) + else: + print(f"Creating new user with email '{user['email']}'") + appbuilder.sm.add_user( + username=user["username"], + first_name=user["firstname"], + last_name=user["lastname"], + email=user["email"], + role=roles, + ) + + users_created.append(user["email"]) + + return users_created, users_updated + + +
[docs]add_role = functools.partial(users_manage_role, remove=False)
+
[docs]remove_role = functools.partial(users_manage_role, remove=True)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/utils.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/utils.html new file mode 100644 index 00000000000..59c080f32f6 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/cli_commands/utils.html @@ -0,0 +1,887 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.cli_commands.utils — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.cli_commands.utils

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from __future__ import annotations
+
+import os
+from contextlib import contextmanager
+from functools import lru_cache
+from typing import TYPE_CHECKING, Generator
+
+from flask import Flask
+
+import airflow
+from airflow.www.extensions.init_appbuilder import init_appbuilder
+from airflow.www.extensions.init_views import init_plugins
+
+if TYPE_CHECKING:
+    from airflow.www.extensions.init_appbuilder import AirflowAppBuilder
+
+
+@lru_cache(maxsize=None)
+def _return_appbuilder(app: Flask) -> AirflowAppBuilder:
+    """Return an appbuilder instance for the given app."""
+    init_appbuilder(app)
+    init_plugins(app)
+    return app.appbuilder  # type: ignore[attr-defined]
+
+
+@contextmanager
+
[docs]def get_application_builder() -> Generator[AirflowAppBuilder, None, None]: + static_folder = os.path.join(os.path.dirname(airflow.__file__), "www", "static") + flask_app = Flask(__name__, static_folder=static_folder) + with flask_app.app_context(): + yield _return_appbuilder(flask_app)
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/decorators/auth.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/decorators/auth.html new file mode 100644 index 00000000000..2fcb14c46ce --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/decorators/auth.html @@ -0,0 +1,965 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.decorators.auth — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.decorators.auth

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import logging
+from functools import wraps
+from typing import Callable, Sequence, TypeVar, cast
+
+from flask import current_app, render_template, request
+
+from airflow.api_connexion.exceptions import PermissionDenied
+from airflow.api_connexion.security import check_authentication
+from airflow.configuration import conf
+from airflow.providers.fab.auth_manager.security_manager.override import FabAirflowSecurityManagerOverride
+from airflow.utils.airflow_flask_app import AirflowApp
+from airflow.utils.net import get_hostname
+from airflow.www.auth import _has_access
+from airflow.www.extensions.init_auth_manager import get_auth_manager
+
+
[docs]T = TypeVar("T", bound=Callable)
+ +
[docs]log = logging.getLogger(__name__)
+ + +def _requires_access_fab(permissions: Sequence[tuple[str, str]] | None = None) -> Callable[[T], T]: + """ + Check current user's permissions against required permissions. + + This decorator is only kept for backward compatible reasons. The decorator + ``airflow.api_connexion.security.requires_access``, which redirects to this decorator, might be used in + user plugins. Thus, we need to keep it. + + :meta private: + """ + appbuilder = cast(AirflowApp, current_app).appbuilder + security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager) + if appbuilder.update_perms: + security_manager.sync_resource_permissions(permissions) + + def requires_access_decorator(func: T): + @wraps(func) + def decorated(*args, **kwargs): + check_authentication() + if security_manager.check_authorization(permissions, kwargs.get("dag_id")): + return func(*args, **kwargs) + raise PermissionDenied() + + return cast(T, decorated) + + return requires_access_decorator + + +def _has_access_fab(permissions: Sequence[tuple[str, str]] | None = None) -> Callable[[T], T]: + """ + Check current user's permissions against required permissions. + + This decorator is only kept for backward compatible reasons. The decorator + ``airflow.www.auth.has_access``, which redirects to this decorator, is widely used in user plugins. + Thus, we need to keep it. + See https://github.com/apache/airflow/pull/33213#discussion_r1346287224 + + :meta private: + """ + + def requires_access_decorator(func: T): + @wraps(func) + def decorated(*args, **kwargs): + __tracebackhide__ = True # Hide from pytest traceback. + + appbuilder = current_app.appbuilder + + dag_id_kwargs = kwargs.get("dag_id") + dag_id_args = request.args.get("dag_id") + dag_id_form = request.form.get("dag_id") + dag_id_json = request.json.get("dag_id") if request.is_json else None + all_dag_ids = [dag_id_kwargs, dag_id_args, dag_id_form, dag_id_json] + unique_dag_ids = set(dag_id for dag_id in all_dag_ids if dag_id is not None) + + if len(unique_dag_ids) > 1: + log.warning( + "There are different dag_ids passed in the request: %s. Returning 403.", unique_dag_ids + ) + log.warning( + "kwargs: %s, args: %s, form: %s, json: %s", + dag_id_kwargs, + dag_id_args, + dag_id_form, + dag_id_json, + ) + return ( + render_template( + "airflow/no_roles_permissions.html", + hostname=get_hostname() + if conf.getboolean("webserver", "EXPOSE_HOSTNAME") + else "redact", + logout_url=get_auth_manager().get_url_logout(), + ), + 403, + ) + dag_id = unique_dag_ids.pop() if unique_dag_ids else None + + return _has_access( + is_authorized=appbuilder.sm.check_authorization(permissions, dag_id), + func=func, + args=args, + kwargs=kwargs, + ) + + return cast(T, decorated) + + return requires_access_decorator +
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/fab_auth_manager.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/fab_auth_manager.html new file mode 100644 index 00000000000..955f4a0bdd6 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/fab_auth_manager.html @@ -0,0 +1,1350 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.fab_auth_manager — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.fab_auth_manager

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import argparse
+from functools import cached_property
+from pathlib import Path
+from typing import TYPE_CHECKING, Container
+
+from connexion import FlaskApi
+from flask import Blueprint, url_for
+from sqlalchemy import select
+from sqlalchemy.orm import Session, joinedload
+
+from airflow.auth.managers.base_auth_manager import BaseAuthManager, ResourceMethod
+from airflow.auth.managers.models.resource_details import (
+    AccessView,
+    ConfigurationDetails,
+    ConnectionDetails,
+    DagAccessEntity,
+    DagDetails,
+    DatasetDetails,
+    PoolDetails,
+    VariableDetails,
+)
+from airflow.auth.managers.utils.fab import get_fab_action_from_method_map, get_method_from_fab_action_map
+from airflow.cli.cli_config import (
+    DefaultHelpParser,
+    GroupCommand,
+)
+from airflow.configuration import conf
+from airflow.exceptions import AirflowConfigException, AirflowException
+from airflow.models import DagModel
+from airflow.providers.fab.auth_manager.cli_commands.definition import (
+    ROLES_COMMANDS,
+    SYNC_PERM_COMMAND,
+    USERS_COMMANDS,
+)
+from airflow.providers.fab.auth_manager.models import Permission, Role, User
+from airflow.security import permissions
+from airflow.security.permissions import (
+    RESOURCE_AUDIT_LOG,
+    RESOURCE_CLUSTER_ACTIVITY,
+    RESOURCE_CONFIG,
+    RESOURCE_CONNECTION,
+    RESOURCE_DAG,
+    RESOURCE_DAG_CODE,
+    RESOURCE_DAG_DEPENDENCIES,
+    RESOURCE_DAG_PREFIX,
+    RESOURCE_DAG_RUN,
+    RESOURCE_DAG_WARNING,
+    RESOURCE_DATASET,
+    RESOURCE_DOCS,
+    RESOURCE_IMPORT_ERROR,
+    RESOURCE_JOB,
+    RESOURCE_PLUGIN,
+    RESOURCE_POOL,
+    RESOURCE_PROVIDER,
+    RESOURCE_SLA_MISS,
+    RESOURCE_TASK_INSTANCE,
+    RESOURCE_TASK_LOG,
+    RESOURCE_TASK_RESCHEDULE,
+    RESOURCE_TRIGGER,
+    RESOURCE_VARIABLE,
+    RESOURCE_WEBSITE,
+    RESOURCE_XCOM,
+)
+from airflow.utils.session import NEW_SESSION, provide_session
+from airflow.utils.yaml import safe_load
+from airflow.www.constants import SWAGGER_BUNDLE, SWAGGER_ENABLED
+from airflow.www.extensions.init_views import _CustomErrorRequestBodyValidator, _LazyResolver
+
+if TYPE_CHECKING:
+    from airflow.auth.managers.models.base_user import BaseUser
+    from airflow.cli.cli_config import (
+        CLICommand,
+    )
+    from airflow.providers.fab.auth_manager.security_manager.override import FabAirflowSecurityManagerOverride
+
+_MAP_DAG_ACCESS_ENTITY_TO_FAB_RESOURCE_TYPE: dict[DagAccessEntity, tuple[str, ...]] = {
+    DagAccessEntity.AUDIT_LOG: (RESOURCE_AUDIT_LOG,),
+    DagAccessEntity.CODE: (RESOURCE_DAG_CODE,),
+    DagAccessEntity.DEPENDENCIES: (RESOURCE_DAG_DEPENDENCIES,),
+    DagAccessEntity.RUN: (RESOURCE_DAG_RUN,),
+    DagAccessEntity.SLA_MISS: (RESOURCE_SLA_MISS,),
+    # RESOURCE_TASK_INSTANCE has been originally misused. RESOURCE_TASK_INSTANCE referred to task definition
+    # AND task instances without making the difference
+    # To be backward compatible, we translate DagAccessEntity.TASK_INSTANCE to RESOURCE_TASK_INSTANCE AND
+    # RESOURCE_DAG_RUN
+    # See https://github.com/apache/airflow/pull/34317#discussion_r1355917769
+    DagAccessEntity.TASK: (RESOURCE_TASK_INSTANCE,),
+    DagAccessEntity.TASK_INSTANCE: (RESOURCE_DAG_RUN, RESOURCE_TASK_INSTANCE),
+    DagAccessEntity.TASK_LOGS: (RESOURCE_TASK_LOG,),
+    DagAccessEntity.TASK_RESCHEDULE: (RESOURCE_TASK_RESCHEDULE,),
+    DagAccessEntity.WARNING: (RESOURCE_DAG_WARNING,),
+    DagAccessEntity.XCOM: (RESOURCE_XCOM,),
+}
+
+_MAP_ACCESS_VIEW_TO_FAB_RESOURCE_TYPE = {
+    AccessView.CLUSTER_ACTIVITY: RESOURCE_CLUSTER_ACTIVITY,
+    AccessView.DOCS: RESOURCE_DOCS,
+    AccessView.IMPORT_ERRORS: RESOURCE_IMPORT_ERROR,
+    AccessView.JOBS: RESOURCE_JOB,
+    AccessView.PLUGINS: RESOURCE_PLUGIN,
+    AccessView.PROVIDERS: RESOURCE_PROVIDER,
+    AccessView.TRIGGERS: RESOURCE_TRIGGER,
+    AccessView.WEBSITE: RESOURCE_WEBSITE,
+}
+
+
+
[docs]class FabAuthManager(BaseAuthManager): + """ + Flask-AppBuilder auth manager. + + This auth manager is responsible for providing a backward compatible user management experience to users. + """ + + @staticmethod +
[docs] def get_cli_commands() -> list[CLICommand]: + """Vends CLI commands to be included in Airflow CLI.""" + return [ + GroupCommand( + name="users", + help="Manage users", + subcommands=USERS_COMMANDS, + ), + GroupCommand( + name="roles", + help="Manage roles", + subcommands=ROLES_COMMANDS, + ), + SYNC_PERM_COMMAND, # not in a command group + ]
+ +
[docs] def get_api_endpoints(self) -> None | Blueprint: + folder = Path(__file__).parents[0].resolve() # this is airflow/auth/managers/fab/ + with folder.joinpath("openapi", "v1.yaml").open() as f: + specification = safe_load(f) + return FlaskApi( + specification=specification, + resolver=_LazyResolver(), + base_path="/auth/fab/v1", + options={"swagger_ui": SWAGGER_ENABLED, "swagger_path": SWAGGER_BUNDLE.__fspath__()}, + strict_validation=True, + validate_responses=True, + validator_map={"body": _CustomErrorRequestBodyValidator}, + ).blueprint
+ +
[docs] def get_user_display_name(self) -> str: + """Return the user's display name associated to the user in session.""" + user = self.get_user() + first_name = user.first_name.strip() if isinstance(user.first_name, str) else "" + last_name = user.last_name.strip() if isinstance(user.last_name, str) else "" + return f"{first_name} {last_name}".strip()
+ +
[docs] def get_user(self) -> User: + """Return the user associated to the user in session.""" + from flask_login import current_user + + return current_user
+ +
[docs] def init(self) -> None: + """Run operations when Airflow is initializing.""" + self._sync_appbuilder_roles()
+ +
[docs] def is_logged_in(self) -> bool: + """Return whether the user is logged in.""" + return not self.get_user().is_anonymous
+ +
[docs] def is_authorized_configuration( + self, + *, + method: ResourceMethod, + details: ConfigurationDetails | None = None, + user: BaseUser | None = None, + ) -> bool: + return self._is_authorized(method=method, resource_type=RESOURCE_CONFIG, user=user)
+ +
[docs] def is_authorized_connection( + self, + *, + method: ResourceMethod, + details: ConnectionDetails | None = None, + user: BaseUser | None = None, + ) -> bool: + return self._is_authorized(method=method, resource_type=RESOURCE_CONNECTION, user=user)
+ +
[docs] def is_authorized_dag( + self, + *, + method: ResourceMethod, + access_entity: DagAccessEntity | None = None, + details: DagDetails | None = None, + user: BaseUser | None = None, + ) -> bool: + """ + Return whether the user is authorized to access the dag. + + There are multiple scenarios: + + 1. ``dag_access`` is not provided which means the user wants to access the DAG itself and not a sub + entity (e.g. DAG runs). + 2. ``dag_access`` is provided which means the user wants to access a sub entity of the DAG + (e.g. DAG runs). + + a. If ``method`` is GET, then check the user has READ permissions on the DAG and the sub entity. + b. Else, check the user has EDIT permissions on the DAG and ``method`` on the sub entity. However, + if no specific DAG is targeted, just check the sub entity. + + :param method: The method to authorize. + :param access_entity: The dag access entity. + :param details: The dag details. + :param user: The user. + """ + if not access_entity: + # Scenario 1 + return self._is_authorized_dag(method=method, details=details, user=user) + else: + # Scenario 2 + resource_types = self._get_fab_resource_types(access_entity) + dag_method: ResourceMethod = "GET" if method == "GET" else "PUT" + + if (details and details.id) and not self._is_authorized_dag( + method=dag_method, details=details, user=user + ): + return False + + return all( + self._is_authorized(method=method, resource_type=resource_type, user=user) + for resource_type in resource_types + )
+ +
[docs] def is_authorized_dataset( + self, *, method: ResourceMethod, details: DatasetDetails | None = None, user: BaseUser | None = None + ) -> bool: + return self._is_authorized(method=method, resource_type=RESOURCE_DATASET, user=user)
+ +
[docs] def is_authorized_pool( + self, *, method: ResourceMethod, details: PoolDetails | None = None, user: BaseUser | None = None + ) -> bool: + return self._is_authorized(method=method, resource_type=RESOURCE_POOL, user=user)
+ +
[docs] def is_authorized_variable( + self, *, method: ResourceMethod, details: VariableDetails | None = None, user: BaseUser | None = None + ) -> bool: + return self._is_authorized(method=method, resource_type=RESOURCE_VARIABLE, user=user)
+ +
[docs] def is_authorized_view(self, *, access_view: AccessView, user: BaseUser | None = None) -> bool: + # "Docs" are only links in the menu, there is no page associated + method: ResourceMethod = "MENU" if access_view == AccessView.DOCS else "GET" + return self._is_authorized( + method=method, resource_type=_MAP_ACCESS_VIEW_TO_FAB_RESOURCE_TYPE[access_view], user=user + )
+ +
[docs] def is_authorized_custom_view( + self, *, method: ResourceMethod, resource_name: str, user: BaseUser | None = None + ): + if not user: + user = self.get_user() + fab_action_name = get_fab_action_from_method_map()[method] + return (fab_action_name, resource_name) in self._get_user_permissions(user)
+ + @provide_session +
[docs] def get_permitted_dag_ids( + self, + *, + methods: Container[ResourceMethod] | None = None, + user=None, + session: Session = NEW_SESSION, + ) -> set[str]: + if not methods: + methods = ["PUT", "GET"] + + if not user: + user = self.get_user() + + if not self.is_logged_in(): + roles = user.roles + else: + if ("GET" in methods and self.is_authorized_dag(method="GET", user=user)) or ( + "PUT" in methods and self.is_authorized_dag(method="PUT", user=user) + ): + # If user is authorized to read/edit all DAGs, return all DAGs + return {dag.dag_id for dag in session.execute(select(DagModel.dag_id))} + user_query = session.scalar( + select(User) + .options( + joinedload(User.roles) + .subqueryload(Role.permissions) + .options(joinedload(Permission.action), joinedload(Permission.resource)) + ) + .where(User.id == user.id) + ) + roles = user_query.roles + + map_fab_action_name_to_method_name = get_method_from_fab_action_map() + resources = set() + for role in roles: + for permission in role.permissions: + action = permission.action.name + if ( + action in map_fab_action_name_to_method_name + and map_fab_action_name_to_method_name[action] in methods + ): + resource = permission.resource.name + if resource == permissions.RESOURCE_DAG: + return {dag.dag_id for dag in session.execute(select(DagModel.dag_id))} + if resource.startswith(permissions.RESOURCE_DAG_PREFIX): + resources.add(resource[len(permissions.RESOURCE_DAG_PREFIX) :]) + else: + resources.add(resource) + return { + dag.dag_id + for dag in session.execute(select(DagModel.dag_id).where(DagModel.dag_id.in_(resources))) + }
+ + @cached_property +
[docs] def security_manager(self) -> FabAirflowSecurityManagerOverride: + """Return the security manager specific to FAB.""" + from airflow.providers.fab.auth_manager.security_manager.override import ( + FabAirflowSecurityManagerOverride, + ) + + sm_from_config = self.appbuilder.get_app.config.get("SECURITY_MANAGER_CLASS") + if sm_from_config: + if not issubclass(sm_from_config, FabAirflowSecurityManagerOverride): + raise AirflowConfigException( + """Your CUSTOM_SECURITY_MANAGER must extend FabAirflowSecurityManagerOverride.""" + ) + return sm_from_config(self.appbuilder) + + return FabAirflowSecurityManagerOverride(self.appbuilder)
+ +
[docs] def get_url_login(self, **kwargs) -> str: + """Return the login page url.""" + if not self.security_manager.auth_view: + raise AirflowException("`auth_view` not defined in the security manager.") + if next_url := kwargs.get("next_url"): + return url_for(f"{self.security_manager.auth_view.endpoint}.login", next=next_url) + else: + return url_for(f"{self.security_manager.auth_view.endpoint}.login")
+ +
[docs] def get_url_logout(self): + """Return the logout page url.""" + if not self.security_manager.auth_view: + raise AirflowException("`auth_view` not defined in the security manager.") + return url_for(f"{self.security_manager.auth_view.endpoint}.logout")
+ +
[docs] def get_url_user_profile(self) -> str | None: + """Return the url to a page displaying info about the current user.""" + if not self.security_manager.user_view: + return None + return url_for(f"{self.security_manager.user_view.endpoint}.userinfo")
+ + def _is_authorized( + self, + *, + method: ResourceMethod, + resource_type: str, + user: BaseUser | None = None, + ) -> bool: + """ + Return whether the user is authorized to perform a given action. + + :param method: the method to perform + :param resource_type: the type of resource the user attempts to perform the action on + :param user: the user to perform the action on. If not provided (or None), it uses the current user + + :meta private: + """ + if not user: + user = self.get_user() + + fab_action = self._get_fab_action(method) + user_permissions = self._get_user_permissions(user) + + return (fab_action, resource_type) in user_permissions + + def _is_authorized_dag( + self, + method: ResourceMethod, + details: DagDetails | None = None, + user: BaseUser | None = None, + ) -> bool: + """ + Return whether the user is authorized to perform a given action on a DAG. + + :param method: the method to perform + :param details: optional details about the DAG + :param user: the user to perform the action on. If not provided (or None), it uses the current user + + :meta private: + """ + is_global_authorized = self._is_authorized(method=method, resource_type=RESOURCE_DAG, user=user) + if is_global_authorized: + return True + + if details and details.id: + # Check whether the user has permissions to access a specific DAG + resource_dag_name = self._resource_name_for_dag(details.id) + return self._is_authorized(method=method, resource_type=resource_dag_name, user=user) + + return False + + @staticmethod + def _get_fab_action(method: ResourceMethod) -> str: + """ + Convert the method to a FAB action. + + :param method: the method to convert + + :meta private: + """ + fab_action_from_method_map = get_fab_action_from_method_map() + if method not in fab_action_from_method_map: + raise AirflowException(f"Unknown method: {method}") + return fab_action_from_method_map[method] + + @staticmethod + def _get_fab_resource_types(dag_access_entity: DagAccessEntity) -> tuple[str, ...]: + """ + Convert a DAG access entity to a tuple of FAB resource type. + + :param dag_access_entity: the DAG access entity + + :meta private: + """ + if dag_access_entity not in _MAP_DAG_ACCESS_ENTITY_TO_FAB_RESOURCE_TYPE: + raise AirflowException(f"Unknown DAG access entity: {dag_access_entity}") + return _MAP_DAG_ACCESS_ENTITY_TO_FAB_RESOURCE_TYPE[dag_access_entity] + + def _resource_name_for_dag(self, dag_id: str) -> str: + """ + Return the FAB resource name for a DAG id. + + :param dag_id: the DAG id + + :meta private: + """ + root_dag_id = self._get_root_dag_id(dag_id) + if root_dag_id == RESOURCE_DAG: + return root_dag_id + if root_dag_id.startswith(RESOURCE_DAG_PREFIX): + return root_dag_id + return f"{RESOURCE_DAG_PREFIX}{root_dag_id}" + + @staticmethod + def _get_user_permissions(user: BaseUser): + """ + Return the user permissions. + + :param user: the user to get permissions for + + :meta private: + """ + return getattr(user, "perms") or [] + + def _get_root_dag_id(self, dag_id: str) -> str: + """ + Return the root DAG id in case of sub DAG, return the DAG id otherwise. + + :param dag_id: the DAG id + + :meta private: + """ + if "." in dag_id: + return self.appbuilder.get_session.scalar( + select(DagModel.dag_id, DagModel.root_dag_id).where(DagModel.dag_id == dag_id).limit(1) + ) + return dag_id + + def _sync_appbuilder_roles(self): + """ + Sync appbuilder roles to DB. + + :meta private: + """ + # Garbage collect old permissions/views after they have been modified. + # Otherwise, when the name of a view or menu is changed, the framework + # will add the new Views and Menus names to the backend, but will not + # delete the old ones. + if conf.getboolean( + "fab", "UPDATE_FAB_PERMS", fallback=conf.getboolean("webserver", "UPDATE_FAB_PERMS") + ): + self.security_manager.sync_roles()
+ + +
[docs]def get_parser() -> argparse.ArgumentParser: + """Generate documentation; used by Sphinx argparse.""" + from airflow.cli.cli_parser import AirflowHelpFormatter, _add_command + + parser = DefaultHelpParser(prog="airflow", formatter_class=AirflowHelpFormatter) + subparsers = parser.add_subparsers(dest="subcommand", metavar="GROUP_OR_COMMAND") + for group_command in FabAuthManager.get_cli_commands(): + _add_command(subparsers, group_command) + return parser
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/models.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/models.html new file mode 100644 index 00000000000..af366aaf49b --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/models.html @@ -0,0 +1,1113 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.models — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.models

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import datetime
+
+# This product contains a modified portion of 'Flask App Builder' developed by Daniel Vaz Gaspar.
+# (https://github.com/dpgaspar/Flask-AppBuilder).
+# Copyright 2013, Daniel Vaz Gaspar
+from typing import TYPE_CHECKING
+
+from flask import current_app, g
+from flask_appbuilder.models.sqla import Model
+from sqlalchemy import (
+    Boolean,
+    Column,
+    DateTime,
+    ForeignKey,
+    Index,
+    Integer,
+    String,
+    Table,
+    UniqueConstraint,
+    event,
+    func,
+    select,
+)
+from sqlalchemy.orm import backref, declared_attr, relationship
+
+from airflow.auth.managers.models.base_user import BaseUser
+from airflow.models.base import Base
+
+"""
+Compatibility note: The models in this file are duplicated from Flask AppBuilder.
+"""
+# Use airflow metadata to create the tables
+Model.metadata = Base.metadata
+
+if TYPE_CHECKING:
+    try:
+        from sqlalchemy import Identity
+    except Exception:
+
[docs] Identity = None
+ + +
[docs]class Action(Model): + """Represents permission actions such as `can_read`.""" + +
[docs] __tablename__ = "ab_permission"
+
[docs] id = Column(Integer, primary_key=True)
+
[docs] name = Column(String(100), unique=True, nullable=False)
+ +
[docs] def __repr__(self): + return self.name
+ + +
[docs]class Resource(Model): + """Represents permission object such as `User` or `Dag`.""" + +
[docs] __tablename__ = "ab_view_menu"
+
[docs] id = Column(Integer, primary_key=True)
+
[docs] name = Column(String(250), unique=True, nullable=False)
+ +
[docs] def __eq__(self, other): + return (isinstance(other, self.__class__)) and (self.name == other.name)
+ +
[docs] def __neq__(self, other): + return self.name != other.name
+ +
[docs] def __repr__(self): + return self.name
+ + +
[docs]assoc_permission_role = Table( + "ab_permission_view_role", + Model.metadata, + Column("id", Integer, primary_key=True), + Column("permission_view_id", Integer, ForeignKey("ab_permission_view.id")), + Column("role_id", Integer, ForeignKey("ab_role.id")), + UniqueConstraint("permission_view_id", "role_id"), +)
+ + +
[docs]class Role(Model): + """Represents a user role to which permissions can be assigned.""" + +
[docs] __tablename__ = "ab_role"
+ +
[docs] id = Column(Integer, primary_key=True)
+
[docs] name = Column(String(64), unique=True, nullable=False)
+
[docs] permissions = relationship("Permission", secondary=assoc_permission_role, backref="role", lazy="joined")
+ +
[docs] def __repr__(self): + return self.name
+ + +
[docs]class Permission(Model): + """Permission pair comprised of an Action + Resource combo.""" + +
[docs] __tablename__ = "ab_permission_view"
+
[docs] __table_args__ = (UniqueConstraint("permission_id", "view_menu_id"),)
+
[docs] id = Column(Integer, primary_key=True)
+
[docs] action_id = Column("permission_id", Integer, ForeignKey("ab_permission.id"))
+
[docs] action = relationship( + "Action", + uselist=False, + lazy="joined", + )
+
[docs] resource_id = Column("view_menu_id", Integer, ForeignKey("ab_view_menu.id"))
+
[docs] resource = relationship( + "Resource", + uselist=False, + lazy="joined", + )
+ +
[docs] def __repr__(self): + return str(self.action).replace("_", " ") + " on " + str(self.resource)
+ + +
[docs]assoc_user_role = Table( + "ab_user_role", + Model.metadata, + Column("id", Integer, primary_key=True), + Column("user_id", Integer, ForeignKey("ab_user.id")), + Column("role_id", Integer, ForeignKey("ab_role.id")), + UniqueConstraint("user_id", "role_id"), +)
+ + +
[docs]class User(Model, BaseUser): + """Represents an Airflow user which has roles assigned to it.""" + +
[docs] __tablename__ = "ab_user"
+
[docs] id = Column(Integer, primary_key=True)
+
[docs] first_name = Column(String(256), nullable=False)
+
[docs] last_name = Column(String(256), nullable=False)
+
[docs] username = Column( + String(512).with_variant(String(512, collation="NOCASE"), "sqlite"), unique=True, nullable=False + )
+
[docs] password = Column(String(256))
+
[docs] active = Column(Boolean, default=True)
+
[docs] email = Column(String(512), unique=True, nullable=False)
+
[docs] last_login = Column(DateTime)
+
[docs] login_count = Column(Integer)
+
[docs] fail_login_count = Column(Integer)
+
[docs] roles = relationship("Role", secondary=assoc_user_role, backref="user", lazy="selectin")
+
[docs] created_on = Column(DateTime, default=datetime.datetime.now, nullable=True)
+
[docs] changed_on = Column(DateTime, default=datetime.datetime.now, nullable=True)
+ + @declared_attr +
[docs] def created_by_fk(self): + return Column(Integer, ForeignKey("ab_user.id"), default=self.get_user_id, nullable=True)
+ + @declared_attr +
[docs] def changed_by_fk(self): + return Column(Integer, ForeignKey("ab_user.id"), default=self.get_user_id, nullable=True)
+ +
[docs] created_by = relationship( + "User", + backref=backref("created", uselist=True), + remote_side=[id], + primaryjoin="User.created_by_fk == User.id", + uselist=False, + )
+
[docs] changed_by = relationship( + "User", + backref=backref("changed", uselist=True), + remote_side=[id], + primaryjoin="User.changed_by_fk == User.id", + uselist=False, + )
+ + @classmethod +
[docs] def get_user_id(cls): + try: + return g.user.get_id() + except Exception: + return None
+ + @property +
[docs] def is_authenticated(self): + return True
+ + @property +
[docs] def is_active(self): + return self.active
+ + @property +
[docs] def is_anonymous(self): + return False
+ + @property +
[docs] def perms(self): + if not self._perms: + # Using the ORM here is _slow_ (Creating lots of objects to then throw them away) since this is in + # the path for every request. Avoid it if we can! + if current_app: + sm = current_app.appbuilder.sm + self._perms: set[tuple[str, str]] = set( + sm.get_session.execute( + select(sm.action_model.name, sm.resource_model.name) + .join(sm.permission_model.action) + .join(sm.permission_model.resource) + .join(sm.permission_model.role) + .where(sm.role_model.user.contains(self)) + ) + ) + else: + self._perms = { + (perm.action.name, perm.resource.name) for role in self.roles for perm in role.permissions + } + return self._perms
+ +
[docs] def get_id(self): + return self.id
+ +
[docs] def get_name(self) -> str: + return self.username or self.email or self.user_id
+ +
[docs] def get_full_name(self): + return f"{self.first_name} {self.last_name}"
+ +
[docs] def __repr__(self): + return self.get_full_name()
+ + _perms = None
+ + +
[docs]class RegisterUser(Model): + """Represents a user registration.""" + +
[docs] __tablename__ = "ab_register_user"
+
[docs] id = Column(Integer, primary_key=True)
+
[docs] first_name = Column(String(256), nullable=False)
+
[docs] last_name = Column(String(256), nullable=False)
+
[docs] username = Column( + String(512).with_variant(String(512, collation="NOCASE"), "sqlite"), unique=True, nullable=False + )
+
[docs] password = Column(String(256))
+
[docs] email = Column(String(512), nullable=False)
+
[docs] registration_date = Column(DateTime, default=datetime.datetime.now, nullable=True)
+
[docs] registration_hash = Column(String(256))
+ + +@event.listens_for(User.__table__, "before_create") +
[docs]def add_index_on_ab_user_username_postgres(table, conn, **kw): + if conn.dialect.name != "postgresql": + return + index_name = "idx_ab_user_username" + if not any(table_index.name == index_name for table_index in table.indexes): + table.indexes.add(Index(index_name, func.lower(table.c.username), unique=True))
+ + +@event.listens_for(RegisterUser.__table__, "before_create") +
[docs]def add_index_on_ab_register_user_username_postgres(table, conn, **kw): + if conn.dialect.name != "postgresql": + return + index_name = "idx_ab_register_user_username" + if not any(table_index.name == index_name for table_index in table.indexes): + table.indexes.add(Index(index_name, func.lower(table.c.username), unique=True))
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/models/anonymous_user.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/models/anonymous_user.html new file mode 100644 index 00000000000..2ad20927583 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/models/anonymous_user.html @@ -0,0 +1,891 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.models.anonymous_user — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.models.anonymous_user

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from flask import current_app
+from flask_login import AnonymousUserMixin
+
+from airflow.auth.managers.models.base_user import BaseUser
+
+
+
[docs]class AnonymousUser(AnonymousUserMixin, BaseUser): + """User object used when no active user is logged in.""" + + _roles: set[tuple[str, str]] = set() + _perms: set[tuple[str, str]] = set() + + @property +
[docs] def roles(self): + if not self._roles: + public_role = current_app.appbuilder.get_app.config["AUTH_ROLE_PUBLIC"] + self._roles = {current_app.appbuilder.sm.find_role(public_role)} if public_role else set() + return self._roles
+ + @roles.setter + def roles(self, roles): + self._roles = roles + self._perms = set() + + @property +
[docs] def perms(self): + if not self._perms: + self._perms = { + (perm.action.name, perm.resource.name) for role in self.roles for perm in role.permissions + } + return self._perms
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/security_manager/constants.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/security_manager/constants.html new file mode 100644 index 00000000000..03cff5e731d --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/security_manager/constants.html @@ -0,0 +1,865 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.security_manager.constants — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.security_manager.constants

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+
[docs]EXISTING_ROLES = { + "Admin", + "Viewer", + "User", + "Op", + "Public", +}
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/security_manager/override.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/security_manager/override.html new file mode 100644 index 00000000000..4ac240714c0 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/security_manager/override.html @@ -0,0 +1,3604 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.security_manager.override — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.security_manager.override

+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import datetime
+import itertools
+import logging
+import os
+import random
+import uuid
+import warnings
+from typing import TYPE_CHECKING, Any, Callable, Collection, Container, Iterable, Sequence
+
+import jwt
+import re2
+from deprecated import deprecated
+from flask import flash, g, has_request_context, session
+from flask_appbuilder import const
+from flask_appbuilder.const import (
+    AUTH_DB,
+    AUTH_LDAP,
+    AUTH_OAUTH,
+    AUTH_OID,
+    AUTH_REMOTE_USER,
+    LOGMSG_ERR_SEC_ADD_REGISTER_USER,
+    LOGMSG_ERR_SEC_AUTH_LDAP,
+    LOGMSG_ERR_SEC_AUTH_LDAP_TLS,
+    LOGMSG_WAR_SEC_LOGIN_FAILED,
+    LOGMSG_WAR_SEC_NOLDAP_OBJ,
+    MICROSOFT_KEY_SET_URL,
+)
+from flask_appbuilder.models.sqla import Base
+from flask_appbuilder.models.sqla.interface import SQLAInterface
+from flask_appbuilder.security.registerviews import (
+    RegisterUserDBView,
+    RegisterUserOAuthView,
+    RegisterUserOIDView,
+)
+from flask_appbuilder.security.views import (
+    AuthDBView,
+    AuthLDAPView,
+    AuthOAuthView,
+    AuthOIDView,
+    AuthRemoteUserView,
+    RegisterUserModelView,
+)
+from flask_babel import lazy_gettext
+from flask_jwt_extended import JWTManager, current_user as current_user_jwt
+from flask_login import LoginManager
+from itsdangerous import want_bytes
+from markupsafe import Markup
+from sqlalchemy import and_, func, inspect, literal, or_, select
+from sqlalchemy.exc import MultipleResultsFound
+from sqlalchemy.orm import Session, joinedload
+from werkzeug.security import check_password_hash, generate_password_hash
+
+from airflow.auth.managers.utils.fab import get_method_from_fab_action_map
+from airflow.configuration import conf
+from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning, RemovedInAirflow3Warning
+from airflow.models import DagBag, DagModel
+from airflow.providers.fab.auth_manager.models import (
+    Action,
+    Permission,
+    RegisterUser,
+    Resource,
+    Role,
+    User,
+    assoc_permission_role,
+)
+from airflow.providers.fab.auth_manager.models.anonymous_user import AnonymousUser
+from airflow.providers.fab.auth_manager.security_manager.constants import EXISTING_ROLES
+from airflow.providers.fab.auth_manager.views.permissions import (
+    ActionModelView,
+    PermissionPairModelView,
+    ResourceModelView,
+)
+from airflow.providers.fab.auth_manager.views.roles_list import CustomRoleModelView
+from airflow.providers.fab.auth_manager.views.user import (
+    CustomUserDBModelView,
+    CustomUserLDAPModelView,
+    CustomUserOAuthModelView,
+    CustomUserOIDModelView,
+    CustomUserRemoteUserModelView,
+)
+from airflow.providers.fab.auth_manager.views.user_edit import (
+    CustomResetMyPasswordView,
+    CustomResetPasswordView,
+    CustomUserInfoEditView,
+)
+from airflow.providers.fab.auth_manager.views.user_stats import CustomUserStatsChartView
+from airflow.security import permissions
+from airflow.utils.session import NEW_SESSION, provide_session
+from airflow.www.extensions.init_auth_manager import get_auth_manager
+from airflow.www.security_manager import AirflowSecurityManagerV2
+from airflow.www.session import AirflowDatabaseSessionInterface
+
+if TYPE_CHECKING:
+    from airflow.auth.managers.base_auth_manager import ResourceMethod
+
+
[docs]log = logging.getLogger(__name__)
+ +# This is the limit of DB user sessions that we consider as "healthy". If you have more sessions that this +# number then we will refuse to delete sessions that have expired and old user sessions when resetting +# user's password, and raise a warning in the UI instead. Usually when you have that many sessions, it means +# that there is something wrong with your deployment - for example you have an automated API call that +# continuously creates new sessions. Such setup should be fixed by reusing sessions or by periodically +# purging the old sessions by using `airflow db clean` command. +
[docs]MAX_NUM_DATABASE_USER_SESSIONS = 50000
+ + +
[docs]class FabAirflowSecurityManagerOverride(AirflowSecurityManagerV2): + """ + This security manager overrides the default AirflowSecurityManager security manager. + + This security manager is used only if the auth manager FabAuthManager is used. It defines everything in + the security manager that is needed for the FabAuthManager to work. Any operation specific to + the AirflowSecurityManager should be defined here instead of AirflowSecurityManager. + + :param appbuilder: The appbuilder. + """ + +
[docs] auth_view = None
+ """ The obj instance for authentication view """ +
[docs] registeruser_view = None
+ """ The obj instance for registering user view """ +
[docs] user_view = None
+ """ The obj instance for user view """ + + """ Models """ +
[docs] user_model = User
+
[docs] role_model = Role
+
[docs] action_model = Action
+
[docs] resource_model = Resource
+
[docs] permission_model = Permission
+ + """ Views """ +
[docs] authdbview = AuthDBView
+ """ Override if you want your own Authentication DB view """ +
[docs] authldapview = AuthLDAPView
+ """ Override if you want your own Authentication LDAP view """ +
[docs] authoidview = AuthOIDView
+ """ Override if you want your own Authentication OID view """ +
[docs] authoauthview = AuthOAuthView
+ """ Override if you want your own Authentication OAuth view """ +
[docs] authremoteuserview = AuthRemoteUserView
+ """ Override if you want your own Authentication REMOTE_USER view """ +
[docs] registeruserdbview = RegisterUserDBView
+ """ Override if you want your own register user db view """ +
[docs] registeruseroidview = RegisterUserOIDView
+ """ Override if you want your own register user OpenID view """ +
[docs] registeruseroauthview = RegisterUserOAuthView
+ """ Override if you want your own register user OAuth view """ +
[docs] actionmodelview = ActionModelView
+
[docs] permissionmodelview = PermissionPairModelView
+
[docs] rolemodelview = CustomRoleModelView
+
[docs] registeruser_model = RegisterUser
+
[docs] registerusermodelview = RegisterUserModelView
+
[docs] resourcemodelview = ResourceModelView
+
[docs] userdbmodelview = CustomUserDBModelView
+
[docs] resetmypasswordview = CustomResetMyPasswordView
+
[docs] resetpasswordview = CustomResetPasswordView
+
[docs] userinfoeditview = CustomUserInfoEditView
+
[docs] userldapmodelview = CustomUserLDAPModelView
+
[docs] useroauthmodelview = CustomUserOAuthModelView
+
[docs] userremoteusermodelview = CustomUserRemoteUserModelView
+
[docs] useroidmodelview = CustomUserOIDModelView
+
[docs] userstatschartview = CustomUserStatsChartView
+ +
[docs] jwt_manager = None
+ """ Flask-JWT-Extended """ +
[docs] oid = None
+ """ Flask-OpenID OpenID """ +
[docs] oauth = None
+
[docs] oauth_remotes: dict[str, Any]
+ """ Initialized (remote_app) providers dict {'provider_name', OBJ } """ + +
[docs] oauth_user_info = None
+ +
[docs] oauth_allow_list: dict[str, list] = {}
+ """ OAuth email allow list """ + + # global resource for dag-level access +
[docs] DAG_RESOURCES = {permissions.RESOURCE_DAG}
+ + ########################################################################### + # PERMISSIONS + ########################################################################### + + # [START security_viewer_perms] +
[docs] VIEWER_PERMISSIONS = [ + (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_DEPENDENCIES), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_CODE), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_RUN), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_DATASET), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_CLUSTER_ACTIVITY), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_POOL), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_IMPORT_ERROR), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_WARNING), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_JOB), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_MY_PASSWORD), + (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_MY_PASSWORD), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_MY_PROFILE), + (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_MY_PROFILE), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_PLUGIN), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_SLA_MISS), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_TASK_INSTANCE), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_TASK_LOG), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_XCOM), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_WEBSITE), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_BROWSE_MENU), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DAG), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DAG_DEPENDENCIES), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DAG_RUN), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DATASET), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_CLUSTER_ACTIVITY), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DOCS), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DOCS_MENU), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_JOB), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_PLUGIN), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_SLA_MISS), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_TASK_INSTANCE), + ]
+ # [END security_viewer_perms] + + # [START security_user_perms] +
[docs] USER_PERMISSIONS = [ + (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_DAG), + (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_DAG), + (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_TASK_INSTANCE), + (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_TASK_INSTANCE), + (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_TASK_INSTANCE), + (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_DAG_RUN), + (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_DAG_RUN), + (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_DAG_RUN), + (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_DATASET), + ]
+ # [END security_user_perms] + + # [START security_op_perms] +
[docs] OP_PERMISSIONS = [ + (permissions.ACTION_CAN_READ, permissions.RESOURCE_CONFIG), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_ADMIN_MENU), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_CONFIG), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_CONNECTION), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_POOL), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_VARIABLE), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_PROVIDER), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_XCOM), + (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_CONNECTION), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_CONNECTION), + (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_CONNECTION), + (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_CONNECTION), + (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_POOL), + (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_POOL), + (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_POOL), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_PROVIDER), + (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_VARIABLE), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_VARIABLE), + (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_VARIABLE), + (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_VARIABLE), + (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_XCOM), + (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_DATASET), + (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_DATASET), + ]
+ # [END security_op_perms] + + # [START security_admin_perms] +
[docs] ADMIN_PERMISSIONS = [ + (permissions.ACTION_CAN_READ, permissions.RESOURCE_AUDIT_LOG), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_AUDIT_LOG), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_TASK_RESCHEDULE), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_TASK_RESCHEDULE), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_TRIGGER), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_TRIGGER), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_PASSWORD), + (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_PASSWORD), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_ROLE), + (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_ROLE), + ]
+ # [END security_admin_perms] + + ########################################################################### + # DEFAULT ROLE CONFIGURATIONS + ########################################################################### + +
[docs] ROLE_CONFIGS: list[dict[str, Any]] = [ + {"role": "Public", "perms": []}, + {"role": "Viewer", "perms": VIEWER_PERMISSIONS}, + { + "role": "User", + "perms": VIEWER_PERMISSIONS + USER_PERMISSIONS, + }, + { + "role": "Op", + "perms": VIEWER_PERMISSIONS + USER_PERMISSIONS + OP_PERMISSIONS, + }, + { + "role": "Admin", + "perms": VIEWER_PERMISSIONS + USER_PERMISSIONS + OP_PERMISSIONS + ADMIN_PERMISSIONS, + }, + ]
+ + # global resource for dag-level access +
[docs] DAG_ACTIONS = permissions.DAG_ACTIONS
+ + def __init__(self, appbuilder): + # done in super, but we need it before we can call super. + self.appbuilder = appbuilder + + self._init_config() + self._init_auth() + self._init_data_model() + # can only call super once data model init has been done + # because of the view.datamodel hack that's done in the init there. + super().__init__(appbuilder=appbuilder) + + self._builtin_roles: dict = self.create_builtin_roles() + + self.create_db() + + # Setup Flask login + self.lm = self.create_login_manager() + + # Setup Flask-Jwt-Extended + self.create_jwt_manager() + + def _get_authentik_jwks(self, jwks_url) -> dict: + import requests + + resp = requests.get(jwks_url) + if resp.status_code == 200: + return resp.json() + return {} + + def _validate_jwt(self, id_token, jwks): + from authlib.jose import JsonWebKey, jwt as authlib_jwt + + keyset = JsonWebKey.import_key_set(jwks) + claims = authlib_jwt.decode(id_token, keyset) + claims.validate() + log.info("JWT token is validated") + return claims + + def _get_authentik_token_info(self, id_token): + me = jwt.decode(id_token, options={"verify_signature": False}) + + verify_signature = self.oauth_remotes["authentik"].client_kwargs.get("verify_signature", True) + if verify_signature: + # Validate the token using authentik certificate + jwks_uri = self.oauth_remotes["authentik"].server_metadata.get("jwks_uri") + if jwks_uri: + jwks = self._get_authentik_jwks(jwks_uri) + if jwks: + return self._validate_jwt(id_token, jwks) + else: + log.error("jwks_uri not specified in OAuth Providers, could not verify token signature") + else: + # Return the token info without validating + log.warning("JWT token is not validated!") + return me + + raise AirflowException("OAuth signature verify failed") + +
[docs] def register_views(self): + """Register FAB auth manager related views.""" + if not self.appbuilder.get_app.config.get("FAB_ADD_SECURITY_VIEWS", True): + return + + if self.auth_user_registration: + if self.auth_type == AUTH_DB: + self.registeruser_view = self.registeruserdbview() + elif self.auth_type == AUTH_OID: + self.registeruser_view = self.registeruseroidview() + elif self.auth_type == AUTH_OAUTH: + self.registeruser_view = self.registeruseroauthview() + if self.registeruser_view: + self.appbuilder.add_view_no_menu(self.registeruser_view) + + self.appbuilder.add_view_no_menu(self.resetpasswordview()) + self.appbuilder.add_view_no_menu(self.resetmypasswordview()) + self.appbuilder.add_view_no_menu(self.userinfoeditview()) + + if self.auth_type == AUTH_DB: + self.user_view = self.userdbmodelview + self.auth_view = self.authdbview() + elif self.auth_type == AUTH_LDAP: + self.user_view = self.userldapmodelview + self.auth_view = self.authldapview() + elif self.auth_type == AUTH_OAUTH: + self.user_view = self.useroauthmodelview + self.auth_view = self.authoauthview() + elif self.auth_type == AUTH_REMOTE_USER: + self.user_view = self.userremoteusermodelview + self.auth_view = self.authremoteuserview() + else: + self.user_view = self.useroidmodelview + self.auth_view = self.authoidview() + + self.appbuilder.add_view_no_menu(self.auth_view) + + # this needs to be done after the view is added, otherwise the blueprint + # is not initialized + if self.is_auth_limited: + self.limiter.limit(self.auth_rate_limit, methods=["POST"])(self.auth_view.blueprint) + + self.user_view = self.appbuilder.add_view( + self.user_view, + "List Users", + icon="fa-user", + label=lazy_gettext("List Users"), + category="Security", + category_icon="fa-cogs", + category_label=lazy_gettext("Security"), + ) + + role_view = self.appbuilder.add_view( + self.rolemodelview, + "List Roles", + icon="fa-group", + label=lazy_gettext("List Roles"), + category="Security", + category_icon="fa-cogs", + ) + role_view.related_views = [self.user_view.__class__] + + if self.userstatschartview: + self.appbuilder.add_view( + self.userstatschartview, + "User's Statistics", + icon="fa-bar-chart-o", + label=lazy_gettext("User's Statistics"), + category="Security", + ) + if self.auth_user_registration: + self.appbuilder.add_view( + self.registerusermodelview, + "User's Statistics", + icon="fa-user-plus", + label=lazy_gettext("User Registrations"), + category="Security", + ) + self.appbuilder.menu.add_separator("Security") + if self.appbuilder.get_app.config.get("FAB_ADD_SECURITY_PERMISSION_VIEW", True): + self.appbuilder.add_view( + self.actionmodelview, + "Actions", + icon="fa-lock", + label=lazy_gettext("Actions"), + category="Security", + ) + if self.appbuilder.get_app.config.get("FAB_ADD_SECURITY_VIEW_MENU_VIEW", True): + self.appbuilder.add_view( + self.resourcemodelview, + "Resources", + icon="fa-list-alt", + label=lazy_gettext("Resources"), + category="Security", + ) + if self.appbuilder.get_app.config.get("FAB_ADD_SECURITY_PERMISSION_VIEWS_VIEW", True): + self.appbuilder.add_view( + self.permissionmodelview, + "Permission Pairs", + icon="fa-link", + label=lazy_gettext("Permissions"), + category="Security", + )
+ + @property +
[docs] def get_session(self): + return self.appbuilder.get_session
+ +
[docs] def create_login_manager(self) -> LoginManager: + """Create the login manager.""" + lm = LoginManager(self.appbuilder.app) + lm.anonymous_user = AnonymousUser + lm.login_view = "login" + lm.user_loader(self.load_user) + return lm
+ +
[docs] def create_jwt_manager(self): + """Create the JWT manager.""" + jwt_manager = JWTManager() + jwt_manager.init_app(self.appbuilder.app) + jwt_manager.user_lookup_loader(self.load_user_jwt)
+ +
[docs] def reset_password(self, userid: int, password: str) -> bool: + """ + Change/Reset a user's password for auth db. + + Password will be hashed and saved. + + :param userid: the user id to reset the password + :param password: the clear text password to reset and save hashed on the db + """ + user = self.get_user_by_id(userid) + user.password = generate_password_hash(password) + self.reset_user_sessions(user) + return self.update_user(user)
+ +
[docs] def reset_user_sessions(self, user: User) -> None: + if isinstance(self.appbuilder.get_app.session_interface, AirflowDatabaseSessionInterface): + interface = self.appbuilder.get_app.session_interface + session = interface.db.session + user_session_model = interface.sql_session_model + num_sessions = session.query(user_session_model).count() + if num_sessions > MAX_NUM_DATABASE_USER_SESSIONS: + self._cli_safe_flash( + f"The old sessions for user {user.username} have <b>NOT</b> been deleted!<br>" + f"You have a lot ({num_sessions}) of user sessions in the 'SESSIONS' table in " + f"your database.<br> " + "This indicates that this deployment might have an automated API calls that create " + "and not reuse sessions.<br>You should consider reusing sessions or cleaning them " + "periodically using db clean.<br>" + "Make sure to reset password for the user again after cleaning the session table " + "to remove old sessions of the user.", + "warning", + ) + else: + for s in session.query(user_session_model): + session_details = interface.serializer.loads(want_bytes(s.data)) + if session_details.get("_user_id") == user.id: + session.delete(s) + else: + self._cli_safe_flash( + "Since you are using `securecookie` session backend mechanism, we cannot prevent " + f"some old sessions for user {user.username} to be reused.<br> If you want to make sure " + "that the user is logged out from all sessions, you should consider using " + "`database` session backend mechanism.<br> You can also change the 'secret_key` " + "webserver configuration for all your webserver instances and restart the webserver. " + "This however will logout all users from all sessions.", + "warning", + )
+ +
[docs] def load_user_jwt(self, _jwt_header, jwt_data): + identity = jwt_data["sub"] + user = self.load_user(identity) + if user.is_active: + # Set flask g.user to JWT user, we can't do it on before request + g.user = user + return user
+ + @property +
[docs] def auth_type(self): + """Get the auth type.""" + return self.appbuilder.get_app.config["AUTH_TYPE"]
+ + @property +
[docs] def is_auth_limited(self) -> bool: + """Is the auth rate limited.""" + return self.appbuilder.get_app.config["AUTH_RATE_LIMITED"]
+ + @property +
[docs] def auth_rate_limit(self) -> str: + """Get the auth rate limit.""" + return self.appbuilder.get_app.config["AUTH_RATE_LIMIT"]
+ + @property +
[docs] def auth_role_public(self): + """Get the public role.""" + return self.appbuilder.get_app.config["AUTH_ROLE_PUBLIC"]
+ + @property +
[docs] def oauth_providers(self): + """Oauth providers.""" + return self.appbuilder.get_app.config["OAUTH_PROVIDERS"]
+ + @property +
[docs] def auth_ldap_tls_cacertdir(self): + """LDAP TLS CA certificate directory.""" + return self.appbuilder.get_app.config["AUTH_LDAP_TLS_CACERTDIR"]
+ + @property +
[docs] def auth_ldap_tls_cacertfile(self): + """LDAP TLS CA certificate file.""" + return self.appbuilder.get_app.config["AUTH_LDAP_TLS_CACERTFILE"]
+ + @property +
[docs] def auth_ldap_tls_certfile(self): + """LDAP TLS certificate file.""" + return self.appbuilder.get_app.config["AUTH_LDAP_TLS_CERTFILE"]
+ + @property +
[docs] def auth_ldap_tls_keyfile(self): + """LDAP TLS key file.""" + return self.appbuilder.get_app.config["AUTH_LDAP_TLS_KEYFILE"]
+ + @property +
[docs] def auth_ldap_allow_self_signed(self): + """LDAP allow self signed.""" + return self.appbuilder.get_app.config["AUTH_LDAP_ALLOW_SELF_SIGNED"]
+ + @property +
[docs] def auth_ldap_tls_demand(self): + """LDAP TLS demand.""" + return self.appbuilder.get_app.config["AUTH_LDAP_TLS_DEMAND"]
+ + @property +
[docs] def auth_ldap_server(self): + """Get the LDAP server object.""" + return self.appbuilder.get_app.config["AUTH_LDAP_SERVER"]
+ + @property +
[docs] def auth_ldap_use_tls(self): + """Should LDAP use TLS.""" + return self.appbuilder.get_app.config["AUTH_LDAP_USE_TLS"]
+ + @property +
[docs] def auth_ldap_bind_user(self): + """LDAP bind user.""" + return self.appbuilder.get_app.config["AUTH_LDAP_BIND_USER"]
+ + @property +
[docs] def auth_ldap_bind_password(self): + """LDAP bind password.""" + return self.appbuilder.get_app.config["AUTH_LDAP_BIND_PASSWORD"]
+ + @property + + + @property +
[docs] def auth_ldap_search_filter(self): + """LDAP search filter.""" + return self.appbuilder.get_app.config["AUTH_LDAP_SEARCH_FILTER"]
+ + @property +
[docs] def auth_ldap_uid_field(self): + """LDAP UID field.""" + return self.appbuilder.get_app.config["AUTH_LDAP_UID_FIELD"]
+ + @property +
[docs] def auth_ldap_firstname_field(self): + """LDAP first name field.""" + return self.appbuilder.get_app.config["AUTH_LDAP_FIRSTNAME_FIELD"]
+ + @property +
[docs] def auth_ldap_lastname_field(self): + """LDAP last name field.""" + return self.appbuilder.get_app.config["AUTH_LDAP_LASTNAME_FIELD"]
+ + @property +
[docs] def auth_ldap_email_field(self): + """LDAP email field.""" + return self.appbuilder.get_app.config["AUTH_LDAP_EMAIL_FIELD"]
+ + @property +
[docs] def auth_ldap_append_domain(self): + """LDAP append domain.""" + return self.appbuilder.get_app.config["AUTH_LDAP_APPEND_DOMAIN"]
+ + @property +
[docs] def auth_ldap_username_format(self): + """LDAP username format.""" + return self.appbuilder.get_app.config["AUTH_LDAP_USERNAME_FORMAT"]
+ + @property +
[docs] def auth_ldap_group_field(self) -> str: + """LDAP group field.""" + return self.appbuilder.get_app.config["AUTH_LDAP_GROUP_FIELD"]
+ + @property +
[docs] def auth_roles_mapping(self) -> dict[str, list[str]]: + """The mapping of auth roles.""" + return self.appbuilder.get_app.config["AUTH_ROLES_MAPPING"]
+ + @property +
[docs] def auth_user_registration_role_jmespath(self) -> str: + """The JMESPATH role to use for user registration.""" + return self.appbuilder.get_app.config["AUTH_USER_REGISTRATION_ROLE_JMESPATH"]
+ + @property +
[docs] def auth_remote_user_env_var(self) -> str: + return self.appbuilder.get_app.config["AUTH_REMOTE_USER_ENV_VAR"]
+ + @property +
[docs] def api_login_allow_multiple_providers(self): + return self.appbuilder.get_app.config["AUTH_API_LOGIN_ALLOW_MULTIPLE_PROVIDERS"]
+ + @property +
[docs] def auth_username_ci(self): + """Get the auth username for CI.""" + return self.appbuilder.get_app.config.get("AUTH_USERNAME_CI", True)
+ + @property +
[docs] def auth_ldap_bind_first(self): + """LDAP bind first.""" + return self.appbuilder.get_app.config["AUTH_LDAP_BIND_FIRST"]
+ + @property +
[docs] def openid_providers(self): + """Openid providers.""" + return self.appbuilder.get_app.config["OPENID_PROVIDERS"]
+ + @property +
[docs] def auth_type_provider_name(self): + provider_to_auth_type = {AUTH_DB: "db", AUTH_LDAP: "ldap"} + return provider_to_auth_type.get(self.auth_type)
+ + @property +
[docs] def auth_user_registration(self): + """Will user self registration be allowed.""" + return self.appbuilder.get_app.config["AUTH_USER_REGISTRATION"]
+ + @property +
[docs] def auth_user_registration_role(self): + """The default user self registration role.""" + return self.appbuilder.get_app.config["AUTH_USER_REGISTRATION_ROLE"]
+ + @property +
[docs] def auth_roles_sync_at_login(self) -> bool: + """Should roles be synced at login.""" + return self.appbuilder.get_app.config["AUTH_ROLES_SYNC_AT_LOGIN"]
+ + @property +
[docs] def auth_role_admin(self): + """Get the admin role.""" + return self.appbuilder.get_app.config["AUTH_ROLE_ADMIN"]
+ + @property + @deprecated( + reason="The 'oauth_whitelists' property is deprecated. Please use 'oauth_allow_list' instead.", + category=AirflowProviderDeprecationWarning, + ) +
[docs] def oauth_whitelists(self): + return self.oauth_allow_list
+ +
[docs] def create_builtin_roles(self): + """Return FAB builtin roles.""" + return self.appbuilder.get_app.config.get("FAB_ROLES", {})
+ + @property +
[docs] def builtin_roles(self): + """Get the builtin roles.""" + return self._builtin_roles
+ +
[docs] def create_admin_standalone(self) -> tuple[str | None, str | None]: + """Create an Admin user with a random password so that users can access airflow.""" + from airflow.configuration import AIRFLOW_HOME, make_group_other_inaccessible + + user_name = "admin" + + # We want a streamlined first-run experience, but we do not want to + # use a preset password as people will inevitably run this on a public + # server. Thus, we make a random password and store it in AIRFLOW_HOME, + # with the reasoning that if you can read that directory, you can see + # the database credentials anyway. + password_path = os.path.join(AIRFLOW_HOME, "standalone_admin_password.txt") + + user_exists = self.find_user(user_name) is not None + we_know_password = os.path.isfile(password_path) + + # If the user does not exist, make a random password and make it + if not user_exists: + print(f"FlaskAppBuilder Authentication Manager: Creating {user_name} user") + if (role := self.find_role("Admin")) is None: + raise AirflowException("Unable to find role 'Admin'") + # password does not contain visually similar characters: ijlIJL1oO0 + password = "".join(random.choices("abcdefghkmnpqrstuvwxyzABCDEFGHKMNPQRSTUVWXYZ23456789", k=16)) + with open(password_path, "w") as file: + file.write(password) + make_group_other_inaccessible(password_path) + self.add_user(user_name, "Admin", "User", "admin@example.com", role, password) + print(f"FlaskAppBuilder Authentication Manager: Created {user_name} user") + # If the user does exist, and we know its password, read the password + elif user_exists and we_know_password: + with open(password_path) as file: + password = file.read().strip() + # Otherwise we don't know the password + else: + password = None + return user_name, password
+ + def _init_config(self): + """ + Initialize config. + + :meta private: + """ + app = self.appbuilder.get_app + # Base Security Config + app.config.setdefault("AUTH_ROLE_ADMIN", "Admin") + app.config.setdefault("AUTH_ROLE_PUBLIC", "Public") + app.config.setdefault("AUTH_TYPE", AUTH_DB) + # Self Registration + app.config.setdefault("AUTH_USER_REGISTRATION", False) + app.config.setdefault("AUTH_USER_REGISTRATION_ROLE", self.auth_role_public) + app.config.setdefault("AUTH_USER_REGISTRATION_ROLE_JMESPATH", None) + # Role Mapping + app.config.setdefault("AUTH_ROLES_MAPPING", {}) + app.config.setdefault("AUTH_ROLES_SYNC_AT_LOGIN", False) + app.config.setdefault("AUTH_API_LOGIN_ALLOW_MULTIPLE_PROVIDERS", False) + + # LDAP Config + if self.auth_type == AUTH_LDAP: + if "AUTH_LDAP_SERVER" not in app.config: + raise ValueError("No AUTH_LDAP_SERVER defined on config with AUTH_LDAP authentication type.") + app.config.setdefault("AUTH_LDAP_SEARCH", "") + app.config.setdefault("AUTH_LDAP_SEARCH_FILTER", "") + app.config.setdefault("AUTH_LDAP_APPEND_DOMAIN", "") + app.config.setdefault("AUTH_LDAP_USERNAME_FORMAT", "") + app.config.setdefault("AUTH_LDAP_BIND_USER", "") + app.config.setdefault("AUTH_LDAP_BIND_PASSWORD", "") + # TLS options + app.config.setdefault("AUTH_LDAP_USE_TLS", False) + app.config.setdefault("AUTH_LDAP_ALLOW_SELF_SIGNED", False) + app.config.setdefault("AUTH_LDAP_TLS_DEMAND", False) + app.config.setdefault("AUTH_LDAP_TLS_CACERTDIR", "") + app.config.setdefault("AUTH_LDAP_TLS_CACERTFILE", "") + app.config.setdefault("AUTH_LDAP_TLS_CERTFILE", "") + app.config.setdefault("AUTH_LDAP_TLS_KEYFILE", "") + # Mapping options + app.config.setdefault("AUTH_LDAP_UID_FIELD", "uid") + app.config.setdefault("AUTH_LDAP_GROUP_FIELD", "memberOf") + app.config.setdefault("AUTH_LDAP_FIRSTNAME_FIELD", "givenName") + app.config.setdefault("AUTH_LDAP_LASTNAME_FIELD", "sn") + app.config.setdefault("AUTH_LDAP_EMAIL_FIELD", "mail") + + if self.auth_type == AUTH_REMOTE_USER: + app.config.setdefault("AUTH_REMOTE_USER_ENV_VAR", "REMOTE_USER") + + # Rate limiting + app.config.setdefault("AUTH_RATE_LIMITED", True) + app.config.setdefault("AUTH_RATE_LIMIT", "5 per 40 second") + + def _init_auth(self): + """ + Initialize authentication configuration. + + :meta private: + """ + app = self.appbuilder.get_app + if self.auth_type == AUTH_OID: + from flask_openid import OpenID + + log.warning( + "AUTH_OID is deprecated and will be removed in version 5. " + "Migrate to other authentication methods." + ) + self.oid = OpenID(app) + + if self.auth_type == AUTH_OAUTH: + from authlib.integrations.flask_client import OAuth + + self.oauth = OAuth(app) + self.oauth_remotes = {} + for provider in self.oauth_providers: + provider_name = provider["name"] + log.debug("OAuth providers init %s", provider_name) + obj_provider = self.oauth.register(provider_name, **provider["remote_app"]) + obj_provider._tokengetter = self.oauth_token_getter + if not self.oauth_user_info: + self.oauth_user_info = self.get_oauth_user_info + # Whitelist only users with matching emails + if "whitelist" in provider: + self.oauth_allow_list[provider_name] = provider["whitelist"] + self.oauth_remotes[provider_name] = obj_provider + + def _init_data_model(self): + user_data_model = SQLAInterface(self.user_model) + if self.auth_type == const.AUTH_DB: + self.userdbmodelview.datamodel = user_data_model + elif self.auth_type == const.AUTH_LDAP: + self.userldapmodelview.datamodel = user_data_model + elif self.auth_type == const.AUTH_OID: + self.useroidmodelview.datamodel = user_data_model + elif self.auth_type == const.AUTH_OAUTH: + self.useroauthmodelview.datamodel = user_data_model + elif self.auth_type == const.AUTH_REMOTE_USER: + self.userremoteusermodelview.datamodel = user_data_model + + if self.userstatschartview: + self.userstatschartview.datamodel = user_data_model + if self.auth_user_registration: + self.registerusermodelview.datamodel = SQLAInterface(self.registeruser_model) + + self.rolemodelview.datamodel = SQLAInterface(self.role_model) + self.actionmodelview.datamodel = SQLAInterface(self.action_model) + self.resourcemodelview.datamodel = SQLAInterface(self.resource_model) + self.permissionmodelview.datamodel = SQLAInterface(self.permission_model) + +
[docs] def create_db(self): + """ + Create the database. + + Creates admin and public roles if they don't exist. + """ + if not self.appbuilder.update_perms: + log.debug("Skipping db since appbuilder disables update_perms") + return + try: + engine = self.get_session.get_bind(mapper=None, clause=None) + inspector = inspect(engine) + if "ab_user" not in inspector.get_table_names(): + log.info(const.LOGMSG_INF_SEC_NO_DB) + Base.metadata.create_all(engine) + log.info(const.LOGMSG_INF_SEC_ADD_DB) + + roles_mapping = self.appbuilder.get_app.config.get("FAB_ROLES_MAPPING", {}) + for pk, name in roles_mapping.items(): + self.update_role(pk, name) + for role_name in self._builtin_roles: + self.add_role(role_name) + if self.auth_role_admin not in self._builtin_roles: + self.add_role(self.auth_role_admin) + self.add_role(self.auth_role_public) + if self.count_users() == 0 and self.auth_role_public != self.auth_role_admin: + log.warning(const.LOGMSG_WAR_SEC_NO_USER) + except Exception as e: + log.error(const.LOGMSG_ERR_SEC_CREATE_DB, e) + exit(1)
+ +
[docs] def get_readable_dags(self, user) -> Iterable[DagModel]: + """Get the DAGs readable by authenticated user.""" + warnings.warn( + "`get_readable_dags` has been deprecated. Please use `get_auth_manager().get_permitted_dag_ids` " + "instead.", + RemovedInAirflow3Warning, + stacklevel=2, + ) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", RemovedInAirflow3Warning) + return self.get_accessible_dags([permissions.ACTION_CAN_READ], user)
+ +
[docs] def get_editable_dags(self, user) -> Iterable[DagModel]: + """Get the DAGs editable by authenticated user.""" + warnings.warn( + "`get_editable_dags` has been deprecated. Please use `get_auth_manager().get_permitted_dag_ids` " + "instead.", + RemovedInAirflow3Warning, + stacklevel=2, + ) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", RemovedInAirflow3Warning) + return self.get_accessible_dags([permissions.ACTION_CAN_EDIT], user)
+ + @provide_session +
[docs] def get_accessible_dags( + self, + user_actions: Container[str] | None, + user, + session: Session = NEW_SESSION, + ) -> Iterable[DagModel]: + warnings.warn( + "`get_accessible_dags` has been deprecated. Please use " + "`get_auth_manager().get_permitted_dag_ids` instead.", + RemovedInAirflow3Warning, + stacklevel=3, + ) + + dag_ids = self.get_accessible_dag_ids(user, user_actions, session) + return session.scalars(select(DagModel).where(DagModel.dag_id.in_(dag_ids)))
+ + @provide_session +
[docs] def get_accessible_dag_ids( + self, + user, + user_actions: Container[str] | None = None, + session: Session = NEW_SESSION, + ) -> set[str]: + warnings.warn( + "`get_accessible_dag_ids` has been deprecated. Please use " + "`get_auth_manager().get_permitted_dag_ids` instead.", + RemovedInAirflow3Warning, + stacklevel=3, + ) + if not user_actions: + user_actions = [permissions.ACTION_CAN_EDIT, permissions.ACTION_CAN_READ] + method_from_fab_action_map = get_method_from_fab_action_map() + user_methods: Container[ResourceMethod] = [ + method_from_fab_action_map[action] + for action in method_from_fab_action_map + if action in user_actions + ] + return get_auth_manager().get_permitted_dag_ids(user=user, methods=user_methods, session=session)
+ + @staticmethod +
[docs] def get_readable_dag_ids(user=None) -> set[str]: + """Get the DAG IDs readable by authenticated user.""" + return get_auth_manager().get_permitted_dag_ids(methods=["GET"], user=user)
+ + @staticmethod +
[docs] def get_editable_dag_ids(user=None) -> set[str]: + """Get the DAG IDs editable by authenticated user.""" + return get_auth_manager().get_permitted_dag_ids(methods=["PUT"], user=user)
+ +
[docs] def can_access_some_dags(self, action: str, dag_id: str | None = None) -> bool: + """Check if user has read or write access to some dags.""" + if dag_id and dag_id != "~": + root_dag_id = self._get_root_dag_id(dag_id) + return self.has_access(action, permissions.resource_name_for_dag(root_dag_id)) + + user = g.user + if action == permissions.ACTION_CAN_READ: + return any(self.get_readable_dag_ids(user)) + return any(self.get_editable_dag_ids(user))
+ +
[docs] def get_all_permissions(self) -> set[tuple[str, str]]: + """Return all permissions as a set of tuples with the action and resource names.""" + return set( + self.appbuilder.get_session.execute( + select(self.action_model.name, self.resource_model.name) + .join(self.permission_model.action) + .join(self.permission_model.resource) + ) + )
+ +
[docs] def create_dag_specific_permissions(self) -> None: + """ + Add permissions to all DAGs. + + Creates 'can_read', 'can_edit', and 'can_delete' permissions for all + DAGs, along with any `access_control` permissions provided in them. + + This does iterate through ALL the DAGs, which can be slow. See `sync_perm_for_dag` + if you only need to sync a single DAG. + """ + perms = self.get_all_permissions() + dagbag = DagBag(read_dags_from_db=True) + dagbag.collect_dags_from_db() + dags = dagbag.dags.values() + + for dag in dags: + root_dag_id = dag.parent_dag.dag_id if dag.parent_dag else dag.dag_id + dag_resource_name = permissions.resource_name_for_dag(root_dag_id) + for action_name in self.DAG_ACTIONS: + if (action_name, dag_resource_name) not in perms: + self._merge_perm(action_name, dag_resource_name) + + if dag.access_control is not None: + self.sync_perm_for_dag(dag_resource_name, dag.access_control)
+ +
[docs] def prefixed_dag_id(self, dag_id: str) -> str: + """Return the permission name for a DAG id.""" + warnings.warn( + "`prefixed_dag_id` has been deprecated. " + "Please use `airflow.security.permissions.resource_name_for_dag` instead.", + RemovedInAirflow3Warning, + stacklevel=2, + ) + root_dag_id = self._get_root_dag_id(dag_id) + return permissions.resource_name_for_dag(root_dag_id)
+ +
[docs] def is_dag_resource(self, resource_name: str) -> bool: + """Determine if a resource belongs to a DAG or all DAGs.""" + if resource_name == permissions.RESOURCE_DAG: + return True + return resource_name.startswith(permissions.RESOURCE_DAG_PREFIX)
+ +
[docs] def sync_perm_for_dag( + self, + dag_id: str, + access_control: dict[str, Collection[str]] | None = None, + ) -> None: + """ + Sync permissions for given dag id. + + The dag id surely exists in our dag bag as only / refresh button or DagBag will call this function. + + :param dag_id: the ID of the DAG whose permissions should be updated + :param access_control: a dict where each key is a role name and + each value is a set() of action names (e.g., + {'can_read'} + :return: + """ + dag_resource_name = permissions.resource_name_for_dag(dag_id) + for dag_action_name in self.DAG_ACTIONS: + self.create_permission(dag_action_name, dag_resource_name) + + if access_control is not None: + self.log.debug("Syncing DAG-level permissions for DAG '%s'", dag_resource_name) + self._sync_dag_view_permissions(dag_resource_name, access_control) + else: + self.log.debug( + "Not syncing DAG-level permissions for DAG '%s' as access control is unset.", + dag_resource_name, + )
+ + def _sync_dag_view_permissions(self, dag_id: str, access_control: dict[str, Collection[str]]) -> None: + """ + Set the access policy on the given DAG's ViewModel. + + :param dag_id: the ID of the DAG whose permissions should be updated + :param access_control: a dict where each key is a role name and + each value is a set() of action names (e.g. {'can_read'}) + """ + dag_resource_name = permissions.resource_name_for_dag(dag_id) + + def _get_or_create_dag_permission(action_name: str) -> Permission | None: + perm = self.get_permission(action_name, dag_resource_name) + if not perm: + self.log.info("Creating new action '%s' on resource '%s'", action_name, dag_resource_name) + perm = self.create_permission(action_name, dag_resource_name) + + return perm + + def _revoke_stale_permissions(resource: Resource): + existing_dag_perms = self.get_resource_permissions(resource) + for perm in existing_dag_perms: + non_admin_roles = [role for role in perm.role if role.name != "Admin"] + for role in non_admin_roles: + target_perms_for_role = access_control.get(role.name, ()) + if perm.action.name not in target_perms_for_role: + self.log.info( + "Revoking '%s' on DAG '%s' for role '%s'", + perm.action, + dag_resource_name, + role.name, + ) + self.remove_permission_from_role(role, perm) + + resource = self.get_resource(dag_resource_name) + if resource: + _revoke_stale_permissions(resource) + + for rolename, action_names in access_control.items(): + role = self.find_role(rolename) + if not role: + raise AirflowException( + f"The access_control mapping for DAG '{dag_id}' includes a role named " + f"'{rolename}', but that role does not exist" + ) + + action_names = set(action_names) + invalid_action_names = action_names - self.DAG_ACTIONS + if invalid_action_names: + raise AirflowException( + f"The access_control map for DAG '{dag_resource_name}' includes " + f"the following invalid permissions: {invalid_action_names}; " + f"The set of valid permissions is: {self.DAG_ACTIONS}" + ) + + for action_name in action_names: + dag_perm = _get_or_create_dag_permission(action_name) + if dag_perm: + self.add_permission_to_role(role, dag_perm) + +
[docs] def add_permissions_view(self, base_action_names, resource_name): # Keep name for compatibility with FAB. + """ + Add an action on a resource to the backend. + + :param base_action_names: + list of permissions from view (all exposed methods): + 'can_add','can_edit' etc... + :param resource_name: + name of the resource to add + """ + resource = self.create_resource(resource_name) + perms = self.get_resource_permissions(resource) + + if not perms: + # No permissions yet on this view + for action_name in base_action_names: + action = self.create_permission(action_name, resource_name) + if self.auth_role_admin not in self.builtin_roles: + admin_role = self.find_role(self.auth_role_admin) + self.add_permission_to_role(admin_role, action) + else: + # Permissions on this view exist but.... + admin_role = self.find_role(self.auth_role_admin) + for action_name in base_action_names: + # Check if base view permissions exist + if not self.perms_include_action(perms, action_name): + action = self.create_permission(action_name, resource_name) + if self.auth_role_admin not in self.builtin_roles: + self.add_permission_to_role(admin_role, action) + for perm in perms: + if perm.action is None: + # Skip this perm, it has a null permission + continue + if perm.action.name not in base_action_names: + # perm to delete + roles = self.get_all_roles() + # del permission from all roles + for role in roles: + # TODO: An action can't be removed from a role. + # This is a bug in FAB. It has been reported. + self.remove_permission_from_role(role, perm) + self.delete_permission(perm.action.name, resource_name) + elif self.auth_role_admin not in self.builtin_roles and perm not in admin_role.permissions: + # Role Admin must have all permissions + self.add_permission_to_role(admin_role, perm)
+ +
[docs] def add_permissions_menu(self, resource_name): + """ + Add menu_access to resource on permission_resource. + + :param resource_name: + The resource name + """ + self.create_resource(resource_name) + perm = self.get_permission("menu_access", resource_name) + if not perm: + perm = self.create_permission("menu_access", resource_name) + if self.auth_role_admin not in self.builtin_roles: + role_admin = self.find_role(self.auth_role_admin) + self.add_permission_to_role(role_admin, perm)
+ +
[docs] def security_cleanup(self, baseviews, menus): + """ + Cleanup all unused permissions from the database. + + :param baseviews: A list of BaseViews class + :param menus: Menu class + """ + resources = self.get_all_resources() + roles = self.get_all_roles() + for resource in resources: + found = False + for baseview in baseviews: + if resource.name == baseview.class_permission_name: + found = True + break + if menus.find(resource.name): + found = True + if not found: + permissions = self.get_resource_permissions(resource) + for permission in permissions: + for role in roles: + self.remove_permission_from_role(role, permission) + self.delete_permission(permission.action.name, resource.name) + self.delete_resource(resource.name)
+ +
[docs] def sync_roles(self) -> None: + """ + Initialize default and custom roles with related permissions. + + 1. Init the default role(Admin, Viewer, User, Op, public) + with related permissions. + 2. Init the custom role(dag-user) with related permissions. + """ + # Create global all-dag permissions + self.create_perm_vm_for_all_dag() + + # Sync the default roles (Admin, Viewer, User, Op, public) with related permissions + self.bulk_sync_roles(self.ROLE_CONFIGS) + + self.add_homepage_access_to_custom_roles() + # init existing roles, the rest role could be created through UI. + self.update_admin_permission() + self.clean_perms()
+ +
[docs] def create_perm_vm_for_all_dag(self) -> None: + """Create perm-vm if not exist and insert into FAB security model for all-dags.""" + # create perm for global logical dag + for resource_name, action_name in itertools.product(self.DAG_RESOURCES, self.DAG_ACTIONS): + self._merge_perm(action_name, resource_name)
+ +
[docs] def add_homepage_access_to_custom_roles(self) -> None: + """Add Website.can_read access to all custom roles.""" + website_permission = self.create_permission(permissions.ACTION_CAN_READ, permissions.RESOURCE_WEBSITE) + custom_roles = [role for role in self.get_all_roles() if role.name not in EXISTING_ROLES] + for role in custom_roles: + self.add_permission_to_role(role, website_permission) + + self.appbuilder.get_session.commit()
+ +
[docs] def update_admin_permission(self) -> None: + """ + Add missing permissions to the table for admin. + + Admin should get all the permissions, except the dag permissions + because Admin already has Dags permission. + Add the missing ones to the table for admin. + """ + session = self.appbuilder.get_session + dag_resources = session.scalars( + select(Resource).where(Resource.name.like(f"{permissions.RESOURCE_DAG_PREFIX}%")) + ) + resource_ids = [resource.id for resource in dag_resources] + + perms = session.scalars(select(Permission).where(~Permission.resource_id.in_(resource_ids))) + perms = [p for p in perms if p.action and p.resource] + + admin = self.find_role("Admin") + admin.permissions = list(set(admin.permissions) | set(perms)) + + session.commit()
+ +
[docs] def clean_perms(self) -> None: + """FAB leaves faulty permissions that need to be cleaned up.""" + self.log.debug("Cleaning faulty perms") + sesh = self.appbuilder.get_session + perms = sesh.query(Permission).filter( + or_( + Permission.action == None, # noqa: E711 + Permission.resource == None, # noqa: E711 + ) + ) + # Since FAB doesn't define ON DELETE CASCADE on these tables, we need + # to delete the _object_ so that SQLA knows to delete the many-to-many + # relationship object too. :( + + deleted_count = 0 + for perm in perms: + sesh.delete(perm) + deleted_count += 1 + sesh.commit() + if deleted_count: + self.log.info("Deleted %s faulty permissions", deleted_count)
+ +
[docs] def permission_exists_in_one_or_more_roles( + self, resource_name: str, action_name: str, role_ids: list[int] + ) -> bool: + """ + Efficiently check if a certain permission exists on a list of role ids; used by `has_access`. + + :param resource_name: The view's name to check if exists on one of the roles + :param action_name: The permission name to check if exists + :param role_ids: a list of Role ids + :return: Boolean + """ + q = ( + self.appbuilder.get_session.query(self.permission_model) + .join( + assoc_permission_role, + and_(self.permission_model.id == assoc_permission_role.c.permission_view_id), + ) + .join(self.role_model) + .join(self.action_model) + .join(self.resource_model) + .filter( + self.resource_model.name == resource_name, + self.action_model.name == action_name, + self.role_model.id.in_(role_ids), + ) + .exists() + ) + # Special case for MSSQL/Oracle (works on PG and MySQL > 8) + # Note: We need to keep MSSQL compatibility as long as this provider package + # might still be updated by Airflow prior 2.9.0 users with MSSQL + if self.appbuilder.get_session.bind.dialect.name in ("mssql", "oracle"): + return self.appbuilder.get_session.query(literal(True)).filter(q).scalar() + return self.appbuilder.get_session.query(q).scalar()
+ +
[docs] def perms_include_action(self, perms, action_name): + return any(perm.action and perm.action.name == action_name for perm in perms)
+ +
[docs] def init_role(self, role_name, perms) -> None: + """ + Initialize the role with actions and related resources. + + :param role_name: + :param perms: + """ + warnings.warn( + "`init_role` has been deprecated. Please use `bulk_sync_roles` instead.", + RemovedInAirflow3Warning, + stacklevel=2, + ) + self.bulk_sync_roles([{"role": role_name, "perms": perms}])
+ +
[docs] def bulk_sync_roles(self, roles: Iterable[dict[str, Any]]) -> None: + """Sync the provided roles and permissions.""" + existing_roles = self._get_all_roles_with_permissions() + non_dag_perms = self._get_all_non_dag_permissions() + + for config in roles: + role_name = config["role"] + perms = config["perms"] + role = existing_roles.get(role_name) or self.add_role(role_name) + + for action_name, resource_name in perms: + perm = non_dag_perms.get((action_name, resource_name)) or self.create_permission( + action_name, resource_name + ) + + if perm not in role.permissions: + self.add_permission_to_role(role, perm)
+ +
[docs] def sync_resource_permissions(self, perms: Iterable[tuple[str, str]] | None = None) -> None: + """Populate resource-based permissions.""" + if not perms: + return + + for action_name, resource_name in perms: + self.create_resource(resource_name) + self.create_permission(action_name, resource_name)
+ + """ + ----------- + Role entity + ----------- + """ + +
[docs] def update_role(self, role_id, name: str) -> Role | None: + """Update a role in the database.""" + role = self.get_session.get(self.role_model, role_id) + if not role: + return None + try: + role.name = name + self.get_session.merge(role) + self.get_session.commit() + log.info(const.LOGMSG_INF_SEC_UPD_ROLE, role) + except Exception as e: + log.error(const.LOGMSG_ERR_SEC_UPD_ROLE, e) + self.get_session.rollback() + return None + return role
+ +
[docs] def add_role(self, name: str) -> Role: + """Add a role in the database.""" + role = self.find_role(name) + if role is None: + try: + role = self.role_model() + role.name = name + self.get_session.add(role) + self.get_session.commit() + log.info(const.LOGMSG_INF_SEC_ADD_ROLE, name) + return role + except Exception as e: + log.error(const.LOGMSG_ERR_SEC_ADD_ROLE, e) + self.get_session.rollback() + return role
+ +
[docs] def find_role(self, name): + """ + Find a role in the database. + + :param name: the role name + """ + return self.get_session.query(self.role_model).filter_by(name=name).one_or_none()
+ +
[docs] def get_all_roles(self): + return self.get_session.query(self.role_model).all()
+ +
[docs] def delete_role(self, role_name: str) -> None: + """ + Delete the given Role. + + :param role_name: the name of a role in the ab_role table + """ + session = self.get_session + role = session.query(Role).filter(Role.name == role_name).first() + if role: + log.info("Deleting role '%s'", role_name) + session.delete(role) + session.commit() + else: + raise AirflowException(f"Role named '{role_name}' does not exist")
+ +
[docs] def get_roles_from_keys(self, role_keys: list[str]) -> set[Role]: + """ + Construct a list of FAB role objects, from a list of keys. + + NOTE: + - keys are things like: "LDAP group DNs" or "OAUTH group names" + - we use AUTH_ROLES_MAPPING to map from keys, to FAB role names + + :param role_keys: the list of FAB role keys + """ + _roles = set() + _role_keys = set(role_keys) + for role_key, fab_role_names in self.auth_roles_mapping.items(): + if role_key in _role_keys: + for fab_role_name in fab_role_names: + fab_role = self.find_role(fab_role_name) + if fab_role: + _roles.add(fab_role) + else: + log.warning("Can't find role specified in AUTH_ROLES_MAPPING: %s", fab_role_name) + return _roles
+ +
[docs] def get_public_role(self): + return self.get_session.query(self.role_model).filter_by(name=self.auth_role_public).one_or_none()
+ + """ + ----------- + User entity + ----------- + """ + +
[docs] def add_user( + self, + username, + first_name, + last_name, + email, + role, + password="", + hashed_password="", + ): + """Create a user.""" + try: + user = self.user_model() + user.first_name = first_name + user.last_name = last_name + user.username = username + user.email = email + user.active = True + user.roles = role if isinstance(role, list) else [role] + if hashed_password: + user.password = hashed_password + else: + user.password = generate_password_hash(password) + self.get_session.add(user) + self.get_session.commit() + log.info(const.LOGMSG_INF_SEC_ADD_USER, username) + return user + except Exception as e: + log.error(const.LOGMSG_ERR_SEC_ADD_USER, e) + self.get_session.rollback() + return False
+ +
[docs] def load_user(self, user_id): + user = self.get_user_by_id(int(user_id)) + if user.is_active: + return user
+ +
[docs] def get_user_by_id(self, pk): + return self.get_session.get(self.user_model, pk)
+ +
[docs] def count_users(self): + """Return the number of users in the database.""" + return self.get_session.query(func.count(self.user_model.id)).scalar()
+ +
[docs] def add_register_user(self, username, first_name, last_name, email, password="", hashed_password=""): + """ + Add a registration request for the user. + + :rtype : RegisterUser + """ + register_user = self.registeruser_model() + register_user.username = username + register_user.email = email + register_user.first_name = first_name + register_user.last_name = last_name + if hashed_password: + register_user.password = hashed_password + else: + register_user.password = generate_password_hash(password) + register_user.registration_hash = str(uuid.uuid1()) + try: + self.get_session.add(register_user) + self.get_session.commit() + return register_user + except Exception as e: + log.error(const.LOGMSG_ERR_SEC_ADD_REGISTER_USER, e) + self.get_session.rollback() + return None
+ +
[docs] def find_user(self, username=None, email=None): + """Find user by username or email.""" + if username: + try: + if self.auth_username_ci: + return ( + self.get_session.query(self.user_model) + .filter(func.lower(self.user_model.username) == func.lower(username)) + .one_or_none() + ) + else: + return ( + self.get_session.query(self.user_model) + .filter(func.lower(self.user_model.username) == func.lower(username)) + .one_or_none() + ) + except MultipleResultsFound: + log.error("Multiple results found for user %s", username) + return None + elif email: + try: + return self.get_session.query(self.user_model).filter_by(email=email).one_or_none() + except MultipleResultsFound: + log.error("Multiple results found for user with email %s", email) + return None
+ +
[docs] def find_register_user(self, registration_hash): + return self.get_session.scalar( + select(self.registeruser_mode) + .where(self.registeruser_model.registration_hash == registration_hash) + .limit(1) + )
+ +
[docs] def update_user(self, user: User) -> bool: + try: + self.get_session.merge(user) + self.get_session.commit() + log.info(const.LOGMSG_INF_SEC_UPD_USER, user) + except Exception as e: + log.error(const.LOGMSG_ERR_SEC_UPD_USER, e) + self.get_session.rollback() + return False + return True
+ +
[docs] def del_register_user(self, register_user): + """ + Delete registration object from database. + + :param register_user: RegisterUser object to delete + """ + try: + self.get_session.delete(register_user) + self.get_session.commit() + return True + except Exception as e: + log.error(const.LOGMSG_ERR_SEC_DEL_REGISTER_USER, e) + self.get_session.rollback() + return False
+ +
[docs] def get_all_users(self): + return self.get_session.query(self.user_model).all()
+ +
[docs] def update_user_auth_stat(self, user, success=True): + """Update user authentication stats. + + This is done upon successful/unsuccessful authentication attempts. + + :param user: + The identified (but possibly not successfully authenticated) user + model + :param success: + Defaults to true, if true increments login_count, updates + last_login, and resets fail_login_count to 0, if false increments + fail_login_count on user model. + """ + if not user.login_count: + user.login_count = 0 + if not user.fail_login_count: + user.fail_login_count = 0 + if success: + user.login_count += 1 + user.last_login = datetime.datetime.now() + user.fail_login_count = 0 + else: + user.fail_login_count += 1 + self.update_user(user)
+ + """ + ------------- + Action entity + ------------- + """ + +
[docs] def get_action(self, name: str) -> Action: + """ + Get an existing action record. + + :param name: name + """ + return self.get_session.query(self.action_model).filter_by(name=name).one_or_none()
+ +
[docs] def create_action(self, name): + """ + Add an action to the backend, model action. + + :param name: + name of the action: 'can_add','can_edit' etc... + """ + action = self.get_action(name) + if action is None: + try: + action = self.action_model() + action.name = name + self.get_session.add(action) + self.get_session.commit() + return action + except Exception as e: + log.error(const.LOGMSG_ERR_SEC_ADD_PERMISSION, e) + self.get_session.rollback() + return action
+ +
[docs] def delete_action(self, name: str) -> bool: + """ + Delete a permission action. + + :param name: Name of action to delete (e.g. can_read). + """ + action = self.get_action(name) + if not action: + log.warning(const.LOGMSG_WAR_SEC_DEL_PERMISSION, name) + return False + try: + perms = ( + self.get_session.query(self.permission_model) + .filter(self.permission_model.action == action) + .all() + ) + if perms: + log.warning(const.LOGMSG_WAR_SEC_DEL_PERM_PVM, action, perms) + return False + self.get_session.delete(action) + self.get_session.commit() + return True + except Exception as e: + log.error(const.LOGMSG_ERR_SEC_DEL_PERMISSION, e) + self.get_session.rollback() + return False
+ + """ + --------------- + Resource entity + --------------- + """ + +
[docs] def get_resource(self, name: str) -> Resource: + """ + Return a resource record by name, if it exists. + + :param name: Name of resource + """ + return self.get_session.query(self.resource_model).filter_by(name=name).one_or_none()
+ +
[docs] def create_resource(self, name) -> Resource: + """ + Create a resource with the given name. + + :param name: The name of the resource to create created. + """ + resource = self.get_resource(name) + if resource is None: + try: + resource = self.resource_model() + resource.name = name + self.get_session.add(resource) + self.get_session.commit() + return resource + except Exception as e: + log.error(const.LOGMSG_ERR_SEC_ADD_VIEWMENU, e) + self.get_session.rollback() + return resource
+ +
[docs] def get_all_resources(self) -> list[Resource]: + """Get all existing resource records.""" + return self.get_session.query(self.resource_model).all()
+ +
[docs] def delete_resource(self, name: str) -> bool: + """ + Delete a Resource from the backend. + + :param name: + name of the resource + """ + resource = self.get_resource(name) + if not resource: + log.warning(const.LOGMSG_WAR_SEC_DEL_VIEWMENU, name) + return False + try: + perms = ( + self.get_session.query(self.permission_model) + .filter(self.permission_model.resource == resource) + .all() + ) + if perms: + log.warning(const.LOGMSG_WAR_SEC_DEL_VIEWMENU_PVM, resource, perms) + return False + self.get_session.delete(resource) + self.get_session.commit() + return True + except Exception as e: + log.error(const.LOGMSG_ERR_SEC_DEL_PERMISSION, e) + self.get_session.rollback() + return False
+ + """ + --------------- + Permission entity + --------------- + """ + +
[docs] def get_permission( + self, + action_name: str, + resource_name: str, + ) -> Permission | None: + """ + Get a permission made with the given action->resource pair, if the permission already exists. + + :param action_name: Name of action + :param resource_name: Name of resource + """ + action = self.get_action(action_name) + resource = self.get_resource(resource_name) + if action and resource: + return ( + self.get_session.query(self.permission_model) + .filter_by(action=action, resource=resource) + .one_or_none() + ) + return None
+ +
[docs] def get_resource_permissions(self, resource: Resource) -> Permission: + """ + Retrieve permission pairs associated with a specific resource object. + + :param resource: Object representing a single resource. + """ + return self.get_session.query(self.permission_model).filter_by(resource_id=resource.id).all()
+ +
[docs] def create_permission(self, action_name, resource_name) -> Permission | None: + """ + Add a permission on a resource to the backend. + + :param action_name: + name of the action to add: 'can_add','can_edit' etc... + :param resource_name: + name of the resource to add + """ + if not (action_name and resource_name): + return None + perm = self.get_permission(action_name, resource_name) + if perm: + return perm + resource = self.create_resource(resource_name) + action = self.create_action(action_name) + perm = self.permission_model() + perm.resource_id, perm.action_id = resource.id, action.id + try: + self.get_session.add(perm) + self.get_session.commit() + log.info(const.LOGMSG_INF_SEC_ADD_PERMVIEW, perm) + return perm + except Exception as e: + log.error(const.LOGMSG_ERR_SEC_ADD_PERMVIEW, e) + self.get_session.rollback() + return None
+ +
[docs] def delete_permission(self, action_name: str, resource_name: str) -> None: + """ + Delete the permission linking an action->resource pair. + + Doesn't delete the underlying action or resource. + + :param action_name: Name of existing action + :param resource_name: Name of existing resource + """ + if not (action_name and resource_name): + return + perm = self.get_permission(action_name, resource_name) + if not perm: + return + roles = ( + self.get_session.query(self.role_model).filter(self.role_model.permissions.contains(perm)).first() + ) + if roles: + log.warning(const.LOGMSG_WAR_SEC_DEL_PERMVIEW, resource_name, action_name, roles) + return + try: + # delete permission on resource + self.get_session.delete(perm) + self.get_session.commit() + # if no more permission on permission view, delete permission + if not self.get_session.query(self.permission_model).filter_by(action=perm.action).all(): + self.delete_action(perm.action.name) + log.info(const.LOGMSG_INF_SEC_DEL_PERMVIEW, action_name, resource_name) + except Exception as e: + log.error(const.LOGMSG_ERR_SEC_DEL_PERMVIEW, e) + self.get_session.rollback()
+ +
[docs] def add_permission_to_role(self, role: Role, permission: Permission | None) -> None: + """ + Add an existing permission pair to a role. + + :param role: The role about to get a new permission. + :param permission: The permission pair to add to a role. + """ + if permission and permission not in role.permissions: + try: + role.permissions.append(permission) + self.get_session.merge(role) + self.get_session.commit() + log.info(const.LOGMSG_INF_SEC_ADD_PERMROLE, permission, role.name) + except Exception as e: + log.error(const.LOGMSG_ERR_SEC_ADD_PERMROLE, e) + self.get_session.rollback()
+ +
[docs] def remove_permission_from_role(self, role: Role, permission: Permission) -> None: + """ + Remove a permission pair from a role. + + :param role: User role containing permissions. + :param permission: Object representing resource-> action pair + """ + if permission in role.permissions: + try: + role.permissions.remove(permission) + self.get_session.merge(role) + self.get_session.commit() + log.info(const.LOGMSG_INF_SEC_DEL_PERMROLE, permission, role.name) + except Exception as e: + log.error(const.LOGMSG_ERR_SEC_DEL_PERMROLE, e) + self.get_session.rollback()
+ +
[docs] def get_oid_identity_url(self, provider_name: str) -> str | None: + """Return the OIDC identity provider URL.""" + for provider in self.openid_providers: + if provider.get("name") == provider_name: + return provider.get("url") + return None
+ + @staticmethod +
[docs] def get_user_roles(user=None): + """ + Get all the roles associated with the user. + + :param user: the ab_user in FAB model. + :return: a list of roles associated with the user. + """ + if user is None: + user = g.user + return user.roles
+ + """ + -------------------- + Auth related methods + -------------------- + """ + +
[docs] def auth_user_ldap(self, username, password): + """ + Authenticate user with LDAP. + + NOTE: this depends on python-ldap module. + + :param username: the username + :param password: the password + """ + # If no username is provided, go away + if (username is None) or username == "": + return None + + # Search the DB for this user + user = self.find_user(username=username) + + # If user is not active, go away + if user and (not user.is_active): + return None + + # If user is not registered, and not self-registration, go away + if (not user) and (not self.auth_user_registration): + return None + + # Ensure python-ldap is installed + try: + import ldap + except ImportError: + log.error("python-ldap library is not installed") + return None + + try: + # LDAP certificate settings + if self.auth_ldap_tls_cacertdir: + ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, self.auth_ldap_tls_cacertdir) + if self.auth_ldap_tls_cacertfile: + ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, self.auth_ldap_tls_cacertfile) + if self.auth_ldap_tls_certfile: + ldap.set_option(ldap.OPT_X_TLS_CERTFILE, self.auth_ldap_tls_certfile) + if self.auth_ldap_tls_keyfile: + ldap.set_option(ldap.OPT_X_TLS_KEYFILE, self.auth_ldap_tls_keyfile) + if self.auth_ldap_allow_self_signed: + ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_ALLOW) + ldap.set_option(ldap.OPT_X_TLS_NEWCTX, 0) + elif self.auth_ldap_tls_demand: + ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_DEMAND) + ldap.set_option(ldap.OPT_X_TLS_NEWCTX, 0) + + # Initialise LDAP connection + con = ldap.initialize(self.auth_ldap_server) + con.set_option(ldap.OPT_REFERRALS, 0) + if self.auth_ldap_use_tls: + try: + con.start_tls_s() + except Exception: + log.error(LOGMSG_ERR_SEC_AUTH_LDAP_TLS, self.auth_ldap_server) + return None + + # Define variables, so we can check if they are set in later steps + user_dn = None + user_attributes = {} + + # Flow 1 - (Indirect Search Bind): + # - in this flow, special bind credentials are used to perform the + # LDAP search + # - in this flow, AUTH_LDAP_SEARCH must be set + if self.auth_ldap_bind_user: + # Bind with AUTH_LDAP_BIND_USER/AUTH_LDAP_BIND_PASSWORD + # (authorizes for LDAP search) + self._ldap_bind_indirect(ldap, con) + + # Search for `username` + # - returns the `user_dn` needed for binding to validate credentials + # - returns the `user_attributes` needed for + # AUTH_USER_REGISTRATION/AUTH_ROLES_SYNC_AT_LOGIN + if self.auth_ldap_search: + user_dn, user_attributes = self._search_ldap(ldap, con, username) + else: + log.error("AUTH_LDAP_SEARCH must be set when using AUTH_LDAP_BIND_USER") + return None + + # If search failed, go away + if user_dn is None: + log.info(LOGMSG_WAR_SEC_NOLDAP_OBJ, username) + return None + + # Bind with user_dn/password (validates credentials) + if not self._ldap_bind(ldap, con, user_dn, password): + if user: + self.update_user_auth_stat(user, False) + + # Invalid credentials, go away + log.info(LOGMSG_WAR_SEC_LOGIN_FAILED, username) + return None + + # Flow 2 - (Direct Search Bind): + # - in this flow, the credentials provided by the end-user are used + # to perform the LDAP search + # - in this flow, we only search LDAP if AUTH_LDAP_SEARCH is set + # - features like AUTH_USER_REGISTRATION & AUTH_ROLES_SYNC_AT_LOGIN + # will only work if AUTH_LDAP_SEARCH is set + else: + # Copy the provided username (so we can apply formatters) + bind_username = username + + # update `bind_username` by applying AUTH_LDAP_APPEND_DOMAIN + # - for Microsoft AD, which allows binding with userPrincipalName + if self.auth_ldap_append_domain: + bind_username = bind_username + "@" + self.auth_ldap_append_domain + + # Update `bind_username` by applying AUTH_LDAP_USERNAME_FORMAT + # - for transforming the username into a DN, + # for example: "uid=%s,ou=example,o=test" + if self.auth_ldap_username_format: + bind_username = self.auth_ldap_username_format % bind_username + + # Bind with bind_username/password + # (validates credentials & authorizes for LDAP search) + if not self._ldap_bind(ldap, con, bind_username, password): + if user: + self.update_user_auth_stat(user, False) + + # Invalid credentials, go away + log.info(LOGMSG_WAR_SEC_LOGIN_FAILED, bind_username) + return None + + # Search for `username` (if AUTH_LDAP_SEARCH is set) + # - returns the `user_attributes` + # needed for AUTH_USER_REGISTRATION/AUTH_ROLES_SYNC_AT_LOGIN + # - we search on `username` not `bind_username`, + # because AUTH_LDAP_APPEND_DOMAIN and AUTH_LDAP_USERNAME_FORMAT + # would result in an invalid search filter + if self.auth_ldap_search: + user_dn, user_attributes = self._search_ldap(ldap, con, username) + + # If search failed, go away + if user_dn is None: + log.info(LOGMSG_WAR_SEC_NOLDAP_OBJ, username) + return None + + # Sync the user's roles + if user and user_attributes and self.auth_roles_sync_at_login: + user.roles = self._ldap_calculate_user_roles(user_attributes) + log.debug("Calculated new roles for user=%r as: %s", user_dn, user.roles) + + # If the user is new, register them + if (not user) and user_attributes and self.auth_user_registration: + user = self.add_user( + username=username, + first_name=self.ldap_extract(user_attributes, self.auth_ldap_firstname_field, ""), + last_name=self.ldap_extract(user_attributes, self.auth_ldap_lastname_field, ""), + email=self.ldap_extract( + user_attributes, + self.auth_ldap_email_field, + f"{username}@email.notfound", + ), + role=self._ldap_calculate_user_roles(user_attributes), + ) + log.debug("New user registered: %s", user) + + # If user registration failed, go away + if not user: + log.info(LOGMSG_ERR_SEC_ADD_REGISTER_USER, username) + return None + + # LOGIN SUCCESS (only if user is now registered) + if user: + self._rotate_session_id() + self.update_user_auth_stat(user) + return user + else: + return None + + except ldap.LDAPError as e: + msg = None + if isinstance(e, dict): + msg = getattr(e, "message", None) + if (msg is not None) and ("desc" in msg): + log.error(LOGMSG_ERR_SEC_AUTH_LDAP, e.message["desc"]) + return None + else: + log.error(e) + return None
+ +
[docs] def auth_user_db(self, username, password): + """ + Authenticate user, auth db style. + + :param username: + The username or registered email address + :param password: + The password, will be tested against hashed password on db + """ + if username is None or username == "": + return None + user = self.find_user(username=username) + if user is None: + user = self.find_user(email=username) + if user is None or (not user.is_active): + # Balance failure and success + check_password_hash( + "pbkdf2:sha256:150000$Z3t6fmj2$22da622d94a1f8118" + "c0976a03d2f18f680bfff877c9a965db9eedc51bc0be87c", + "password", + ) + log.info(LOGMSG_WAR_SEC_LOGIN_FAILED, username) + return None + elif check_password_hash(user.password, password): + self._rotate_session_id() + self.update_user_auth_stat(user, True) + return user + else: + self.update_user_auth_stat(user, False) + log.info(LOGMSG_WAR_SEC_LOGIN_FAILED, username) + return None
+ +
[docs] def oauth_user_info_getter( + self, + func: Callable[[AirflowSecurityManagerV2, str, dict[str, Any] | None], dict[str, Any]], + ): + """ + Get OAuth user info for all the providers. + + Receives provider and response return a dict with the information returned from the provider. + The returned user info dict should have its keys with the same name as the User Model. + + Use it like this an example for GitHub :: + + @appbuilder.sm.oauth_user_info_getter + def my_oauth_user_info(sm, provider, response=None): + if provider == "github": + me = sm.oauth_remotes[provider].get("user") + return {"username": me.data.get("login")} + return {} + """ + + def wraps(provider: str, response: dict[str, Any] | None = None) -> dict[str, Any]: + return func(self, provider, response) + + self.oauth_user_info = wraps + return wraps
+ +
[docs] def get_oauth_user_info(self, provider: str, resp: dict[str, Any]) -> dict[str, Any]: + """There are different OAuth APIs with different ways to retrieve user info. + + All providers have different ways to retrieve user info. + """ + # for GITHUB + if provider == "github" or provider == "githublocal": + me = self.oauth_remotes[provider].get("user") + data = me.json() + log.debug("User info from GitHub: %s", data) + return {"username": "github_" + data.get("login")} + # for twitter + if provider == "twitter": + me = self.oauth_remotes[provider].get("account/settings.json") + data = me.json() + log.debug("User info from Twitter: %s", data) + return {"username": "twitter_" + data.get("screen_name", "")} + # for linkedin + if provider == "linkedin": + me = self.oauth_remotes[provider].get( + "people/~:(id,email-address,first-name,last-name)?format=json" + ) + data = me.json() + log.debug("User info from LinkedIn: %s", data) + return { + "username": "linkedin_" + data.get("id", ""), + "email": data.get("email-address", ""), + "first_name": data.get("firstName", ""), + "last_name": data.get("lastName", ""), + } + # for Google + if provider == "google": + me = self.oauth_remotes[provider].get("userinfo") + data = me.json() + log.debug("User info from Google: %s", data) + return { + "username": "google_" + data.get("id", ""), + "first_name": data.get("given_name", ""), + "last_name": data.get("family_name", ""), + "email": data.get("email", ""), + } + if provider == "azure": + me = self._decode_and_validate_azure_jwt(resp["id_token"]) + log.debug("User info from Azure: %s", me) + # https://learn.microsoft.com/en-us/azure/active-directory/develop/id-token-claims-reference#payload-claims + return { + "email": me["email"] if "email" in me else me["upn"], + "first_name": me.get("given_name", ""), + "last_name": me.get("family_name", ""), + "username": me["oid"], + "role_keys": me.get("roles", []), + } + # for OpenShift + if provider == "openshift": + me = self.oauth_remotes[provider].get("apis/user.openshift.io/v1/users/~") + data = me.json() + log.debug("User info from OpenShift: %s", data) + return {"username": "openshift_" + data.get("metadata").get("name")} + # for Okta + if provider == "okta": + me = self.oauth_remotes[provider].get("userinfo") + data = me.json() + log.debug("User info from Okta: %s", data) + return { + "username": f"{provider}_{data['sub']}", + "first_name": data.get("given_name", ""), + "last_name": data.get("family_name", ""), + "email": data["email"], + "role_keys": data.get("groups", []), + } + # for Auth0 + if provider == "auth0": + data = self.appbuilder.sm.oauth_remotes[provider].userinfo() + log.debug("User info from Auth0: %s", data) + return { + "username": f"{provider}_{data['sub']}", + "first_name": data.get("given_name", ""), + "last_name": data.get("family_name", ""), + "email": data["email"], + "role_keys": data.get("groups", []), + } + # for Keycloak + if provider in ["keycloak", "keycloak_before_17"]: + me = self.oauth_remotes[provider].get("openid-connect/userinfo") + me.raise_for_status() + data = me.json() + log.debug("User info from Keycloak: %s", data) + return { + "username": data.get("preferred_username", ""), + "first_name": data.get("given_name", ""), + "last_name": data.get("family_name", ""), + "email": data.get("email", ""), + } + + # for Authentik + if provider == "authentik": + id_token = resp["id_token"] + me = self._get_authentik_token_info(id_token) + log.debug("User info from authentik: %s", me) + return { + "email": me["preferred_username"], + "first_name": me.get("given_name", ""), + "username": me["nickname"], + "role_keys": me.get("groups", []), + } + + else: + return {}
+ + @staticmethod +
[docs] def oauth_token_getter(): + """Get authentication (OAuth) token.""" + token = session.get("oauth") + log.debug("Token Get: %s", token) + return token
+ +
[docs] def check_authorization( + self, + perms: Sequence[tuple[str, str]] | None = None, + dag_id: str | None = None, + ) -> bool: + """Check the logged-in user has the specified permissions.""" + if not perms: + return True + + for perm in perms: + if perm in ( + (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG), + (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_DAG), + (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_DAG), + ): + can_access_all_dags = self.has_access(*perm) + if not can_access_all_dags: + action = perm[0] + if not self.can_access_some_dags(action, dag_id): + return False + elif not self.has_access(*perm): + return False + + return True
+ +
[docs] def set_oauth_session(self, provider, oauth_response): + """Set the current session with OAuth user secrets.""" + # Get this provider key names for token_key and token_secret + token_key = self.get_oauth_token_key_name(provider) + token_secret = self.get_oauth_token_secret_name(provider) + # Save users token on encrypted session cookie + session["oauth"] = ( + oauth_response[token_key], + oauth_response.get(token_secret, ""), + ) + session["oauth_provider"] = provider
+ +
[docs] def get_oauth_token_key_name(self, provider): + """ + Return the token_key name for the oauth provider. + + If none is configured defaults to oauth_token + this is configured using OAUTH_PROVIDERS and token_key key. + """ + for _provider in self.oauth_providers: + if _provider["name"] == provider: + return _provider.get("token_key", "oauth_token")
+ +
[docs] def get_oauth_token_secret_name(self, provider): + """Get the ``token_secret`` name for the oauth provider. + + If none is configured, defaults to ``oauth_secret``. This is configured + using ``OAUTH_PROVIDERS`` and ``token_secret``. + """ + for _provider in self.oauth_providers: + if _provider["name"] == provider: + return _provider.get("token_secret", "oauth_token_secret")
+ +
[docs] def auth_user_oauth(self, userinfo): + """ + Authenticate user with OAuth. + + :userinfo: dict with user information + (keys are the same as User model columns) + """ + # extract the username from `userinfo` + if "username" in userinfo: + username = userinfo["username"] + elif "email" in userinfo: + username = userinfo["email"] + else: + log.error("OAUTH userinfo does not have username or email %s", userinfo) + return None + + # If username is empty, go away + if (username is None) or username == "": + return None + + # Search the DB for this user + user = self.find_user(username=username) + + # If user is not active, go away + if user and (not user.is_active): + return None + + # If user is not registered, and not self-registration, go away + if (not user) and (not self.auth_user_registration): + return None + + # Sync the user's roles + if user and self.auth_roles_sync_at_login: + user.roles = self._oauth_calculate_user_roles(userinfo) + log.debug("Calculated new roles for user=%r as: %s", username, user.roles) + + # If the user is new, register them + if (not user) and self.auth_user_registration: + user = self.add_user( + username=username, + first_name=userinfo.get("first_name", ""), + last_name=userinfo.get("last_name", ""), + email=userinfo.get("email", "") or f"{username}@email.notfound", + role=self._oauth_calculate_user_roles(userinfo), + ) + log.debug("New user registered: %s", user) + + # If user registration failed, go away + if not user: + log.error("Error creating a new OAuth user %s", username) + return None + + # LOGIN SUCCESS (only if user is now registered) + if user: + self._rotate_session_id() + self.update_user_auth_stat(user) + return user + else: + return None
+ +
[docs] def auth_user_oid(self, email): + """ + Openid user Authentication. + + :param email: user's email to authenticate + """ + user = self.find_user(email=email) + if user is None or (not user.is_active): + log.info(LOGMSG_WAR_SEC_LOGIN_FAILED, email) + return None + else: + self._rotate_session_id() + self.update_user_auth_stat(user) + return user
+ +
[docs] def auth_user_remote_user(self, username): + """ + REMOTE_USER user Authentication. + + :param username: user's username for remote auth + """ + user = self.find_user(username=username) + + # User does not exist, create one if auto user registration. + if user is None and self.auth_user_registration: + user = self.add_user( + # All we have is REMOTE_USER, so we set + # the other fields to blank. + username=username, + first_name=username, + last_name="-", + email=username + "@email.notfound", + role=self.find_role(self.auth_user_registration_role), + ) + + # If user does not exist on the DB and not auto user registration, + # or user is inactive, go away. + elif user is None or (not user.is_active): + log.info(LOGMSG_WAR_SEC_LOGIN_FAILED, username) + return None + + self._rotate_session_id() + self.update_user_auth_stat(user) + return user
+ +
[docs] def get_user_menu_access(self, menu_names: list[str] | None = None) -> set[str]: + if get_auth_manager().is_logged_in(): + return self._get_user_permission_resources(g.user, "menu_access", resource_names=menu_names) + elif current_user_jwt: + return self._get_user_permission_resources( + # the current_user_jwt is a lazy proxy, so we need to ignore type checking + current_user_jwt, # type: ignore[arg-type] + "menu_access", + resource_names=menu_names, + ) + else: + return self._get_user_permission_resources(None, "menu_access", resource_names=menu_names)
+ + @staticmethod +
[docs] def ldap_extract_list(ldap_dict: dict[str, list[bytes]], field_name: str) -> list[str]: + raw_list = ldap_dict.get(field_name, []) + # decode - removing empty strings + return [x.decode("utf-8") for x in raw_list if x.decode("utf-8")]
+ + @staticmethod +
[docs] def ldap_extract(ldap_dict: dict[str, list[bytes]], field_name: str, fallback: str) -> str: + raw_value = ldap_dict.get(field_name, [b""]) + # decode - if empty string, default to fallback, otherwise take first element + return raw_value[0].decode("utf-8") or fallback
+ + """ + --------------- + Private methods + --------------- + """ + + def _rotate_session_id(self): + """Rotate the session ID. + + We need to do this upon successful authentication when using the + database session backend. + """ + if conf.get("webserver", "SESSION_BACKEND") == "database": + session.sid = str(uuid.uuid4()) + + def _get_microsoft_jwks(self) -> list[dict[str, Any]]: + import requests + + return requests.get(MICROSOFT_KEY_SET_URL).json() + + def _decode_and_validate_azure_jwt(self, id_token: str) -> dict[str, str]: + verify_signature = self.oauth_remotes["azure"].client_kwargs.get("verify_signature", False) + if verify_signature: + from authlib.jose import JsonWebKey, jwt as authlib_jwt + + keyset = JsonWebKey.import_key_set(self._get_microsoft_jwks()) + claims = authlib_jwt.decode(id_token, keyset) + claims.validate() + return claims + + return jwt.decode(id_token, options={"verify_signature": False}) + + def _ldap_bind_indirect(self, ldap, con) -> None: + """ + Attempt to bind to LDAP using the AUTH_LDAP_BIND_USER. + + :param ldap: The ldap module reference + :param con: The ldap connection + """ + if not self.auth_ldap_bind_user: + # always check AUTH_LDAP_BIND_USER is set before calling this method + raise ValueError("AUTH_LDAP_BIND_USER must be set") + + try: + log.debug("LDAP bind indirect TRY with username: %r", self.auth_ldap_bind_user) + con.simple_bind_s(self.auth_ldap_bind_user, self.auth_ldap_bind_password) + log.debug("LDAP bind indirect SUCCESS with username: %r", self.auth_ldap_bind_user) + except ldap.INVALID_CREDENTIALS as ex: + log.error("AUTH_LDAP_BIND_USER and AUTH_LDAP_BIND_PASSWORD are not valid LDAP bind credentials") + raise ex + + def _search_ldap(self, ldap, con, username): + """ + Search LDAP for user. + + :param ldap: The ldap module reference + :param con: The ldap connection + :param username: username to match with AUTH_LDAP_UID_FIELD + :return: ldap object array + """ + if not self.auth_ldap_search: + # always check AUTH_LDAP_SEARCH is set before calling this method + raise ValueError("AUTH_LDAP_SEARCH must be set") + + # build the filter string for the LDAP search + if self.auth_ldap_search_filter: + filter_str = f"(&{self.auth_ldap_search_filter}({self.auth_ldap_uid_field}={username}))" + else: + filter_str = f"({self.auth_ldap_uid_field}={username})" + + # build what fields to request in the LDAP search + request_fields = [ + self.auth_ldap_firstname_field, + self.auth_ldap_lastname_field, + self.auth_ldap_email_field, + ] + if self.auth_roles_mapping: + request_fields.append(self.auth_ldap_group_field) + + # perform the LDAP search + log.debug( + "LDAP search for %r with fields %s in scope %r", filter_str, request_fields, self.auth_ldap_search + ) + raw_search_result = con.search_s( + self.auth_ldap_search, ldap.SCOPE_SUBTREE, filter_str, request_fields + ) + log.debug("LDAP search returned: %s", raw_search_result) + + # Remove any search referrals from results + search_result = [ + (dn, attrs) for dn, attrs in raw_search_result if dn is not None and isinstance(attrs, dict) + ] + + # only continue if 0 or 1 results were returned + if len(search_result) > 1: + log.error( + "LDAP search for %r in scope '%a' returned multiple results", + self.auth_ldap_search, + filter_str, + ) + return None, None + + try: + # extract the DN + user_dn = search_result[0][0] + # extract the other attributes + user_info = search_result[0][1] + # return + return user_dn, user_info + except (IndexError, NameError): + return None, None + + @staticmethod + def _ldap_bind(ldap, con, dn: str, password: str) -> bool: + """Validates/binds the provided dn/password with the LDAP sever.""" + try: + log.debug("LDAP bind TRY with username: %r", dn) + con.simple_bind_s(dn, password) + log.debug("LDAP bind SUCCESS with username: %r", dn) + return True + except ldap.INVALID_CREDENTIALS: + return False + + def _ldap_calculate_user_roles(self, user_attributes: dict[str, list[bytes]]) -> list[str]: + user_role_objects = set() + + # apply AUTH_ROLES_MAPPING + if self.auth_roles_mapping: + user_role_keys = self.ldap_extract_list(user_attributes, self.auth_ldap_group_field) + user_role_objects.update(self.get_roles_from_keys(user_role_keys)) + + # apply AUTH_USER_REGISTRATION + if self.auth_user_registration: + registration_role_name = self.auth_user_registration_role + + # lookup registration role in flask db + fab_role = self.find_role(registration_role_name) + if fab_role: + user_role_objects.add(fab_role) + else: + log.warning("Can't find AUTH_USER_REGISTRATION role: %s", registration_role_name) + + return list(user_role_objects) + + def _oauth_calculate_user_roles(self, userinfo) -> list[str]: + user_role_objects = set() + + # apply AUTH_ROLES_MAPPING + if self.auth_roles_mapping: + user_role_keys = userinfo.get("role_keys", []) + user_role_objects.update(self.get_roles_from_keys(user_role_keys)) + + # apply AUTH_USER_REGISTRATION_ROLE + if self.auth_user_registration: + registration_role_name = self.auth_user_registration_role + + # if AUTH_USER_REGISTRATION_ROLE_JMESPATH is set, + # use it for the registration role + if self.auth_user_registration_role_jmespath: + import jmespath + + registration_role_name = jmespath.search(self.auth_user_registration_role_jmespath, userinfo) + + # lookup registration role in flask db + fab_role = self.find_role(registration_role_name) + if fab_role: + user_role_objects.add(fab_role) + else: + log.warning("Can't find AUTH_USER_REGISTRATION role: %s", registration_role_name) + + return list(user_role_objects) + + def _get_user_permission_resources( + self, user: User | None, action_name: str, resource_names: list[str] | None = None + ) -> set[str]: + """Get resource names with a certain action name that a user has access to. + + Mainly used to fetch all menu permissions on a single db call, will also + check public permissions and builtin roles + """ + if not resource_names: + resource_names = [] + + db_role_ids = [] + if user is None: + # include public role + roles = [self.get_public_role()] + else: + roles = user.roles + # First check against builtin (statically configured) roles + # because no database query is needed + result = set() + for role in roles: + if role.name in self.builtin_roles: + for resource_name in resource_names: + if self._has_access_builtin_roles(role, action_name, resource_name): + result.add(resource_name) + else: + db_role_ids.append(role.id) + # Then check against database-stored roles + role_resource_names = [ + perm.resource.name for perm in self.filter_roles_by_perm_with_action(action_name, db_role_ids) + ] + result.update(role_resource_names) + return result + + def _has_access_builtin_roles(self, role, action_name: str, resource_name: str) -> bool: + """Check permission on builtin role.""" + perms = self.builtin_roles.get(role.name, []) + for _resource_name, _action_name in perms: + if re2.match(_resource_name, resource_name) and re2.match(_action_name, action_name): + return True + return False + + def _merge_perm(self, action_name: str, resource_name: str) -> None: + """ + Add the new (action, resource) to assoc_permission_role if it doesn't exist. + + It will add the related entry to ab_permission and ab_resource two meta tables as well. + + :param action_name: Name of the action + :param resource_name: Name of the resource + """ + action = self.get_action(action_name) + resource = self.get_resource(resource_name) + perm = None + if action and resource: + perm = self.appbuilder.get_session.scalar( + select(self.permission_model).filter_by(action=action, resource=resource).limit(1) + ) + if not perm and action_name and resource_name: + self.create_permission(action_name, resource_name) + + def _get_all_roles_with_permissions(self) -> dict[str, Role]: + """Return a dict with a key of role name and value of role with early loaded permissions.""" + return { + r.name: r + for r in self.appbuilder.get_session.scalars( + select(self.role_model).options(joinedload(self.role_model.permissions)) + ).unique() + } + + def _get_all_non_dag_permissions(self) -> dict[tuple[str, str], Permission]: + """ + Get permissions except those that are for specific DAGs. + + Return a dict with a key of (action_name, resource_name) and value of permission + with all permissions except those that are for specific DAGs. + """ + return { + (action_name, resource_name): viewmodel + for action_name, resource_name, viewmodel in ( + self.appbuilder.get_session.execute( + select(self.action_model.name, self.resource_model.name, self.permission_model) + .join(self.permission_model.action) + .join(self.permission_model.resource) + .where(~self.resource_model.name.like(f"{permissions.RESOURCE_DAG_PREFIX}%")) + ) + ) + } + +
[docs] def filter_roles_by_perm_with_action(self, action_name: str, role_ids: list[int]): + """Find roles with permission.""" + return ( + self.appbuilder.get_session.query(self.permission_model) + .join( + assoc_permission_role, + and_(self.permission_model.id == assoc_permission_role.c.permission_view_id), + ) + .join(self.role_model) + .join(self.action_model) + .join(self.resource_model) + .filter( + self.action_model.name == action_name, + self.role_model.id.in_(role_ids), + ) + ).all()
+ + def _get_root_dag_id(self, dag_id: str) -> str: + if "." in dag_id: + dm = self.appbuilder.get_session.execute( + select(DagModel.dag_id, DagModel.root_dag_id).where(DagModel.dag_id == dag_id) + ).one() + return dm.root_dag_id or dm.dag_id + return dag_id + + @staticmethod + def _cli_safe_flash(text: str, level: str) -> None: + """Show a flash in a web context or prints a message if not.""" + if has_request_context(): + flash(Markup(text), level) + else: + getattr(log, level)(text.replace("<br>", "\n").replace("<b>", "*").replace("</b>", "*"))
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/permissions.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/permissions.html new file mode 100644 index 00000000000..bca5b99606b --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/permissions.html @@ -0,0 +1,929 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.views.permissions — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.views.permissions

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from flask_appbuilder.security.views import (
+    PermissionModelView,
+    PermissionViewModelView,
+    ViewMenuModelView,
+)
+from flask_babel import lazy_gettext
+
+from airflow.security import permissions
+
+
+
[docs]class ActionModelView(PermissionModelView): + """Customize permission names for FAB's builtin PermissionModelView.""" + +
[docs] class_permission_name = permissions.RESOURCE_ACTION
+
[docs] route_base = "/actions"
+
[docs] method_permission_name = { + "list": "read", + }
+
[docs] base_permissions = [ + permissions.ACTION_CAN_READ, + ]
+ +
[docs] list_title = lazy_gettext("List Actions")
+
[docs] show_title = lazy_gettext("Show Action")
+
[docs] add_title = lazy_gettext("Add Action")
+
[docs] edit_title = lazy_gettext("Edit Action")
+ +
[docs] label_columns = {"name": lazy_gettext("Name")}
+ + +
[docs]class PermissionPairModelView(PermissionViewModelView): + """Customize permission names for FAB's builtin PermissionViewModelView.""" + +
[docs] class_permission_name = permissions.RESOURCE_PERMISSION
+
[docs] route_base = "/permissions"
+
[docs] method_permission_name = { + "list": "read", + }
+
[docs] base_permissions = [ + permissions.ACTION_CAN_READ, + ]
+ +
[docs] list_title = lazy_gettext("List Permissions")
+
[docs] show_title = lazy_gettext("Show Permission")
+
[docs] add_title = lazy_gettext("Add Permission")
+
[docs] edit_title = lazy_gettext("Edit Permission")
+ +
[docs] label_columns = { + "action": lazy_gettext("Action"), + "resource": lazy_gettext("Resource"), + }
+
[docs] list_columns = ["action", "resource"]
+ + +
[docs]class ResourceModelView(ViewMenuModelView): + """Customize permission names for FAB's builtin ViewMenuModelView.""" + +
[docs] class_permission_name = permissions.RESOURCE_RESOURCE
+
[docs] route_base = "/resources"
+
[docs] method_permission_name = { + "list": "read", + }
+
[docs] base_permissions = [ + permissions.ACTION_CAN_READ, + ]
+ +
[docs] list_title = lazy_gettext("List Resources")
+
[docs] show_title = lazy_gettext("Show Resource")
+
[docs] add_title = lazy_gettext("Add Resource")
+
[docs] edit_title = lazy_gettext("Edit Resource")
+ +
[docs] label_columns = {"name": lazy_gettext("Name")}
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/roles_list.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/roles_list.html new file mode 100644 index 00000000000..e4d3079784a --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/roles_list.html @@ -0,0 +1,881 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.views.roles_list — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.views.roles_list

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from flask_appbuilder.security.views import RoleModelView
+
+from airflow.security import permissions
+
+
+
[docs]class CustomRoleModelView(RoleModelView): + """Customize permission names for FAB's builtin RoleModelView.""" + +
[docs] class_permission_name = permissions.RESOURCE_ROLE
+
[docs] method_permission_name = { + "delete": "delete", + "download": "read", + "show": "read", + "list": "read", + "edit": "edit", + "add": "create", + "copy_role": "create", + }
+
[docs] base_permissions = [ + permissions.ACTION_CAN_CREATE, + permissions.ACTION_CAN_READ, + permissions.ACTION_CAN_EDIT, + permissions.ACTION_CAN_DELETE, + ]
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/user.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/user.html new file mode 100644 index 00000000000..731c040f04b --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/user.html @@ -0,0 +1,1027 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.views.user — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.views.user

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from __future__ import annotations
+
+from flask import request
+from flask_appbuilder import expose
+from flask_appbuilder.security.decorators import has_access
+from flask_appbuilder.security.views import (
+    UserDBModelView,
+    UserLDAPModelView,
+    UserOAuthModelView,
+    UserOIDModelView,
+    UserRemoteUserModelView,
+)
+
+from airflow.security import permissions
+
+
+
[docs]class MultiResourceUserMixin: + """Remaps UserModelView permissions to new resources and actions.""" + + _class_permission_name = permissions.RESOURCE_USER + +
[docs] class_permission_name_mapping = { + "userinfoedit": permissions.RESOURCE_MY_PROFILE, + "userinfo": permissions.RESOURCE_MY_PROFILE, + }
+ +
[docs] method_permission_name = { + "userinfo": "read", + "download": "read", + "show": "read", + "list": "read", + "edit": "edit", + "userinfoedit": "edit", + "delete": "delete", + }
+ +
[docs] base_permissions = [ + permissions.ACTION_CAN_READ, + permissions.ACTION_CAN_EDIT, + permissions.ACTION_CAN_DELETE, + ]
+ + @property +
[docs] def class_permission_name(self): + """Returns appropriate permission name depending on request method name.""" + if request: + action_name = request.view_args.get("name") + _, method_name = request.url_rule.endpoint.rsplit(".", 1) + if method_name == "action" and action_name: + return self.class_permission_name_mapping.get(action_name, self._class_permission_name) + if method_name: + return self.class_permission_name_mapping.get(method_name, self._class_permission_name) + return self._class_permission_name
+ + @class_permission_name.setter + def class_permission_name(self, name): + self._class_permission_name = name + + @expose("/show/<pk>", methods=["GET"]) + @has_access +
[docs] def show(self, pk): + pk = self._deserialize_pk_if_composite(pk) + widgets = self._show(pk) + widgets["show"].template_args["actions"].pop("userinfoedit", None) + widgets["show"].template_args["actions"].pop("resetmypassword", None) + return self.render_template( + self.show_template, + pk=pk, + title=self.show_title, + widgets=widgets, + related_views=self._related_views, + )
+ + +
[docs]class CustomUserLDAPModelView(MultiResourceUserMixin, UserLDAPModelView): + """Customize permission names for FAB's builtin UserLDAPModelView.""" + + _class_permission_name = permissions.RESOURCE_USER + +
[docs] class_permission_name_mapping = { + "userinfoedit": permissions.RESOURCE_MY_PROFILE, + "userinfo": permissions.RESOURCE_MY_PROFILE, + }
+ +
[docs] method_permission_name = { + "add": "create", + "userinfo": "read", + "download": "read", + "show": "read", + "list": "read", + "edit": "edit", + "userinfoedit": "edit", + "delete": "delete", + }
+ +
[docs] base_permissions = [ + permissions.ACTION_CAN_CREATE, + permissions.ACTION_CAN_READ, + permissions.ACTION_CAN_EDIT, + permissions.ACTION_CAN_DELETE, + ]
+ + +
[docs]class CustomUserOAuthModelView(MultiResourceUserMixin, UserOAuthModelView): + """Customize permission names for FAB's builtin UserOAuthModelView."""
+ + +
[docs]class CustomUserOIDModelView(MultiResourceUserMixin, UserOIDModelView): + """Customize permission names for FAB's builtin UserOIDModelView."""
+ + +
[docs]class CustomUserRemoteUserModelView(MultiResourceUserMixin, UserRemoteUserModelView): + """Customize permission names for FAB's builtin UserRemoteUserModelView.""" + + _class_permission_name = permissions.RESOURCE_USER + +
[docs] class_permission_name_mapping = { + "userinfoedit": permissions.RESOURCE_MY_PROFILE, + "userinfo": permissions.RESOURCE_MY_PROFILE, + }
+ +
[docs] method_permission_name = { + "add": "create", + "userinfo": "read", + "download": "read", + "show": "read", + "list": "read", + "edit": "edit", + "userinfoedit": "edit", + "delete": "delete", + }
+ +
[docs] base_permissions = [ + permissions.ACTION_CAN_CREATE, + permissions.ACTION_CAN_READ, + permissions.ACTION_CAN_EDIT, + permissions.ACTION_CAN_DELETE, + ]
+ + +
[docs]class CustomUserDBModelView(MultiResourceUserMixin, UserDBModelView): + """Customize permission names for FAB's builtin UserDBModelView.""" + + _class_permission_name = permissions.RESOURCE_USER + +
[docs] class_permission_name_mapping = { + "resetmypassword": permissions.RESOURCE_MY_PASSWORD, + "resetpasswords": permissions.RESOURCE_PASSWORD, + "userinfoedit": permissions.RESOURCE_MY_PROFILE, + "userinfo": permissions.RESOURCE_MY_PROFILE, + }
+ +
[docs] method_permission_name = { + "add": "create", + "download": "read", + "show": "read", + "list": "read", + "edit": "edit", + "delete": "delete", + "resetmypassword": "read", + "resetpasswords": "read", + "userinfo": "read", + "userinfoedit": "read", + }
+ +
[docs] base_permissions = [ + permissions.ACTION_CAN_CREATE, + permissions.ACTION_CAN_READ, + permissions.ACTION_CAN_EDIT, + permissions.ACTION_CAN_DELETE, + ]
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/user_edit.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/user_edit.html new file mode 100644 index 00000000000..37af8686bf7 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/user_edit.html @@ -0,0 +1,899 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.views.user_edit — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.views.user_edit

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from flask_appbuilder.security.views import (
+    ResetMyPasswordView,
+    ResetPasswordView,
+    UserInfoEditView,
+)
+
+from airflow.security import permissions
+
+
+
[docs]class CustomUserInfoEditView(UserInfoEditView): + """Customize permission names for FAB's builtin UserInfoEditView.""" + +
[docs] class_permission_name = permissions.RESOURCE_MY_PROFILE
+
[docs] route_base = "/userinfoeditview"
+
[docs] method_permission_name = { + "this_form_get": "edit", + "this_form_post": "edit", + }
+
[docs] base_permissions = [permissions.ACTION_CAN_EDIT, permissions.ACTION_CAN_READ]
+ + +
[docs]class CustomResetMyPasswordView(ResetMyPasswordView): + """Customize permission names for FAB's builtin ResetMyPasswordView.""" + +
[docs] class_permission_name = permissions.RESOURCE_MY_PASSWORD
+
[docs] method_permission_name = { + "this_form_get": "read", + "this_form_post": "edit", + }
+
[docs] base_permissions = [permissions.ACTION_CAN_EDIT, permissions.ACTION_CAN_READ]
+ + +
[docs]class CustomResetPasswordView(ResetPasswordView): + """Customize permission names for FAB's builtin ResetPasswordView.""" + +
[docs] class_permission_name = permissions.RESOURCE_PASSWORD
+
[docs] method_permission_name = { + "this_form_get": "read", + "this_form_post": "edit", + }
+ +
[docs] base_permissions = [permissions.ACTION_CAN_EDIT, permissions.ACTION_CAN_READ]
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/user_stats.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/user_stats.html new file mode 100644 index 00000000000..f1035ca39ee --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/airflow/providers/fab/auth_manager/views/user_stats.html @@ -0,0 +1,872 @@ + + + + + + + + + + + + airflow.providers.fab.auth_manager.views.user_stats — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Source code for airflow.providers.fab.auth_manager.views.user_stats

+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from flask_appbuilder.security.views import UserStatsChartView
+
+from airflow.security import permissions
+
+
+
[docs]class CustomUserStatsChartView(UserStatsChartView): + """Customize permission names for FAB's builtin UserStatsChartView.""" + +
[docs] class_permission_name = permissions.RESOURCE_USER_STATS_CHART
+
[docs] route_base = "/userstatschartview"
+
[docs] method_permission_name = { + "chart": "read", + "list": "read", + }
+
[docs] base_permissions = [permissions.ACTION_CAN_READ]
+
+ + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/index.html new file mode 100644 index 00000000000..a37a76b195f --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_modules/index.html @@ -0,0 +1,856 @@ + + + + + + + + + + + + Overview: module code — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + + +
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/auth/backend/basic_auth/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/auth/backend/basic_auth/index.rst.txt new file mode 100644 index 00000000000..bd7a1de093e --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/auth/backend/basic_auth/index.rst.txt @@ -0,0 +1,59 @@ +:py:mod:`airflow.providers.fab.auth_manager.api.auth.backend.basic_auth` +======================================================================== + +.. py:module:: airflow.providers.fab.auth_manager.api.auth.backend.basic_auth + +.. autoapi-nested-parse:: + + Basic authentication backend. + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.api.auth.backend.basic_auth.init_app + airflow.providers.fab.auth_manager.api.auth.backend.basic_auth.auth_current_user + airflow.providers.fab.auth_manager.api.auth.backend.basic_auth.requires_authentication + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.api.auth.backend.basic_auth.CLIENT_AUTH + airflow.providers.fab.auth_manager.api.auth.backend.basic_auth.T + + +.. py:data:: CLIENT_AUTH + :type: tuple[str, str] | Any | None + + + +.. py:data:: T + + + +.. py:function:: init_app(_) + + Initialize authentication backend. + + +.. py:function:: auth_current_user() + + Authenticate and set current user if Authorization header exists. + + +.. py:function:: requires_authentication(function) + + Decorate functions that require authentication. + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/auth/backend/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/auth/backend/index.rst.txt new file mode 100644 index 00000000000..c268dc5a0ad --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/auth/backend/index.rst.txt @@ -0,0 +1,16 @@ +:py:mod:`airflow.providers.fab.auth_manager.api.auth.backend` +============================================================= + +.. py:module:: airflow.providers.fab.auth_manager.api.auth.backend + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + basic_auth/index.rst + kerberos_auth/index.rst + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/auth/backend/kerberos_auth/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/auth/backend/kerberos_auth/index.rst.txt new file mode 100644 index 00000000000..904a728622a --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/auth/backend/kerberos_auth/index.rst.txt @@ -0,0 +1,50 @@ +:py:mod:`airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth` +=========================================================================== + +.. py:module:: airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth.find_user + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth.log + airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth.CLIENT_AUTH + airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth.init_app + airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth.requires_authentication + + +.. py:data:: log + + + +.. py:data:: CLIENT_AUTH + :type: tuple[str, str] | Any | None + + + +.. py:function:: find_user(username=None, email=None) + + +.. py:data:: init_app + + + +.. py:data:: requires_authentication + + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/auth/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/auth/index.rst.txt new file mode 100644 index 00000000000..fe7e1115375 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/auth/index.rst.txt @@ -0,0 +1,15 @@ +:py:mod:`airflow.providers.fab.auth_manager.api.auth` +===================================================== + +.. py:module:: airflow.providers.fab.auth_manager.api.auth + + +Subpackages +----------- +.. toctree:: + :titlesonly: + :maxdepth: 3 + + backend/index.rst + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/index.rst.txt new file mode 100644 index 00000000000..cd6d045cae3 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api/index.rst.txt @@ -0,0 +1,15 @@ +:py:mod:`airflow.providers.fab.auth_manager.api` +================================================ + +.. py:module:: airflow.providers.fab.auth_manager.api + + +Subpackages +----------- +.. toctree:: + :titlesonly: + :maxdepth: 3 + + auth/index.rst + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api_endpoints/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api_endpoints/index.rst.txt new file mode 100644 index 00000000000..f73f1af6b9d --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api_endpoints/index.rst.txt @@ -0,0 +1,16 @@ +:py:mod:`airflow.providers.fab.auth_manager.api_endpoints` +========================================================== + +.. py:module:: airflow.providers.fab.auth_manager.api_endpoints + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + role_and_permission_endpoint/index.rst + user_endpoint/index.rst + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api_endpoints/role_and_permission_endpoint/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api_endpoints/role_and_permission_endpoint/index.rst.txt new file mode 100644 index 00000000000..8fd2c1dc415 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api_endpoints/role_and_permission_endpoint/index.rst.txt @@ -0,0 +1,54 @@ +:py:mod:`airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint` +======================================================================================= + +.. py:module:: airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint.get_role + airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint.get_roles + airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint.get_permissions + airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint.delete_role + airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint.patch_role + airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint.post_role + + + +.. py:function:: get_role(*, role_name) + + Get role. + + +.. py:function:: get_roles(*, order_by = 'name', limit, offset = None) + + Get roles. + + +.. py:function:: get_permissions(*, limit, offset = None) + + Get permissions. + + +.. py:function:: delete_role(*, role_name) + + Delete a role. + + +.. py:function:: patch_role(*, role_name, update_mask = None) + + Update a role. + + +.. py:function:: post_role() + + Create a new role. + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api_endpoints/user_endpoint/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api_endpoints/user_endpoint/index.rst.txt new file mode 100644 index 00000000000..ddd231c8d33 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/api_endpoints/user_endpoint/index.rst.txt @@ -0,0 +1,48 @@ +:py:mod:`airflow.providers.fab.auth_manager.api_endpoints.user_endpoint` +======================================================================== + +.. py:module:: airflow.providers.fab.auth_manager.api_endpoints.user_endpoint + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.api_endpoints.user_endpoint.get_user + airflow.providers.fab.auth_manager.api_endpoints.user_endpoint.get_users + airflow.providers.fab.auth_manager.api_endpoints.user_endpoint.post_user + airflow.providers.fab.auth_manager.api_endpoints.user_endpoint.patch_user + airflow.providers.fab.auth_manager.api_endpoints.user_endpoint.delete_user + + + +.. py:function:: get_user(*, username) + + Get a user. + + +.. py:function:: get_users(*, limit, order_by = 'id', offset = None) + + Get users. + + +.. py:function:: post_user() + + Create a new user. + + +.. py:function:: patch_user(*, username, update_mask = None) + + Update a user. + + +.. py:function:: delete_user(*, username) + + Delete a user. + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/definition/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/definition/index.rst.txt new file mode 100644 index 00000000000..9ada5796523 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/definition/index.rst.txt @@ -0,0 +1,111 @@ +:py:mod:`airflow.providers.fab.auth_manager.cli_commands.definition` +==================================================================== + +.. py:module:: airflow.providers.fab.auth_manager.cli_commands.definition + + +Module Contents +--------------- + +.. py:data:: ARG_USERNAME + + + +.. py:data:: ARG_USERNAME_OPTIONAL + + + +.. py:data:: ARG_FIRSTNAME + + + +.. py:data:: ARG_LASTNAME + + + +.. py:data:: ARG_ROLE + + + +.. py:data:: ARG_EMAIL + + + +.. py:data:: ARG_EMAIL_OPTIONAL + + + +.. py:data:: ARG_PASSWORD + + + +.. py:data:: ARG_USE_RANDOM_PASSWORD + + + +.. py:data:: ARG_USER_IMPORT + + + +.. py:data:: ARG_USER_EXPORT + + + +.. py:data:: ARG_CREATE_ROLE + + + +.. py:data:: ARG_LIST_ROLES + + + +.. py:data:: ARG_ROLES + + + +.. py:data:: ARG_PERMISSIONS + + + +.. py:data:: ARG_ROLE_RESOURCE + + + +.. py:data:: ARG_ROLE_ACTION + + + +.. py:data:: ARG_ROLE_ACTION_REQUIRED + + + +.. py:data:: ARG_ROLE_IMPORT + + + +.. py:data:: ARG_ROLE_EXPORT + + + +.. py:data:: ARG_ROLE_EXPORT_FMT + + + +.. py:data:: ARG_INCLUDE_DAGS + + + +.. py:data:: USERS_COMMANDS + :value: () + + + +.. py:data:: ROLES_COMMANDS + :value: () + + + +.. py:data:: SYNC_PERM_COMMAND + + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/index.rst.txt new file mode 100644 index 00000000000..5ced77b62ee --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/index.rst.txt @@ -0,0 +1,19 @@ +:py:mod:`airflow.providers.fab.auth_manager.cli_commands` +========================================================= + +.. py:module:: airflow.providers.fab.auth_manager.cli_commands + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + definition/index.rst + role_command/index.rst + sync_perm_command/index.rst + user_command/index.rst + utils/index.rst + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/role_command/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/role_command/index.rst.txt new file mode 100644 index 00000000000..8570d575d9c --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/role_command/index.rst.txt @@ -0,0 +1,67 @@ +:py:mod:`airflow.providers.fab.auth_manager.cli_commands.role_command` +====================================================================== + +.. py:module:: airflow.providers.fab.auth_manager.cli_commands.role_command + +.. autoapi-nested-parse:: + + Roles sub-commands. + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.cli_commands.role_command.roles_list + airflow.providers.fab.auth_manager.cli_commands.role_command.roles_create + airflow.providers.fab.auth_manager.cli_commands.role_command.roles_delete + airflow.providers.fab.auth_manager.cli_commands.role_command.roles_add_perms + airflow.providers.fab.auth_manager.cli_commands.role_command.roles_del_perms + airflow.providers.fab.auth_manager.cli_commands.role_command.roles_export + airflow.providers.fab.auth_manager.cli_commands.role_command.roles_import + + + +.. py:function:: roles_list(args) + + List all existing roles. + + +.. py:function:: roles_create(args) + + Create new empty role in DB. + + +.. py:function:: roles_delete(args) + + Delete role in DB. + + +.. py:function:: roles_add_perms(args) + + Add permissions to role in DB. + + +.. py:function:: roles_del_perms(args) + + Delete permissions from role in DB. + + +.. py:function:: roles_export(args) + + Export all the roles from the database to a file including permissions. + + +.. py:function:: roles_import(args) + + Import all the roles into the db from the given json file including their permissions. + + Note, if a role already exists in the db, it is not overwritten, even when the permissions change. + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/sync_perm_command/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/sync_perm_command/index.rst.txt new file mode 100644 index 00000000000..8716ffe6dc9 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/sync_perm_command/index.rst.txt @@ -0,0 +1,29 @@ +:py:mod:`airflow.providers.fab.auth_manager.cli_commands.sync_perm_command` +=========================================================================== + +.. py:module:: airflow.providers.fab.auth_manager.cli_commands.sync_perm_command + +.. autoapi-nested-parse:: + + Sync permission command. + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.cli_commands.sync_perm_command.sync_perm + + + +.. py:function:: sync_perm(args) + + Update permissions for existing roles and DAGs. + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/user_command/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/user_command/index.rst.txt new file mode 100644 index 00000000000..603bed76a7d --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/user_command/index.rst.txt @@ -0,0 +1,122 @@ +:py:mod:`airflow.providers.fab.auth_manager.cli_commands.user_command` +====================================================================== + +.. py:module:: airflow.providers.fab.auth_manager.cli_commands.user_command + +.. autoapi-nested-parse:: + + User sub-commands. + + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.cli_commands.user_command.UserSchema + + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.cli_commands.user_command.users_list + airflow.providers.fab.auth_manager.cli_commands.user_command.users_create + airflow.providers.fab.auth_manager.cli_commands.user_command.user_reset_password + airflow.providers.fab.auth_manager.cli_commands.user_command.users_delete + airflow.providers.fab.auth_manager.cli_commands.user_command.users_manage_role + airflow.providers.fab.auth_manager.cli_commands.user_command.users_export + airflow.providers.fab.auth_manager.cli_commands.user_command.users_import + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.cli_commands.user_command.add_role + airflow.providers.fab.auth_manager.cli_commands.user_command.remove_role + + +.. py:class:: UserSchema(*, only = None, exclude = (), many = False, context = None, load_only = (), dump_only = (), partial = None, unknown = None) + + + Bases: :py:obj:`marshmallow.Schema` + + user collection item schema. + + .. py:attribute:: id + + + + .. py:attribute:: firstname + + + + .. py:attribute:: lastname + + + + .. py:attribute:: username + + + + .. py:attribute:: email + + + + .. py:attribute:: roles + + + + +.. py:function:: users_list(args) + + List users at the command line. + + +.. py:function:: users_create(args) + + Create new user in the DB. + + +.. py:function:: user_reset_password(args) + + Reset user password user from DB. + + +.. py:function:: users_delete(args) + + Delete user from DB. + + +.. py:function:: users_manage_role(args, remove=False) + + Delete or appends user roles. + + +.. py:function:: users_export(args) + + Export all users to the json file. + + +.. py:function:: users_import(args) + + Import users from the json file. + + +.. py:data:: add_role + + + +.. py:data:: remove_role + + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/utils/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/utils/index.rst.txt new file mode 100644 index 00000000000..7ace7c2b6f0 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/cli_commands/utils/index.rst.txt @@ -0,0 +1,22 @@ +:py:mod:`airflow.providers.fab.auth_manager.cli_commands.utils` +=============================================================== + +.. py:module:: airflow.providers.fab.auth_manager.cli_commands.utils + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.cli_commands.utils.get_application_builder + + + +.. py:function:: get_application_builder() + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/decorators/auth/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/decorators/auth/index.rst.txt new file mode 100644 index 00000000000..c031132caf5 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/decorators/auth/index.rst.txt @@ -0,0 +1,17 @@ +:py:mod:`airflow.providers.fab.auth_manager.decorators.auth` +============================================================ + +.. py:module:: airflow.providers.fab.auth_manager.decorators.auth + + +Module Contents +--------------- + +.. py:data:: T + + + +.. py:data:: log + + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/decorators/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/decorators/index.rst.txt new file mode 100644 index 00000000000..1fe14369bea --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/decorators/index.rst.txt @@ -0,0 +1,15 @@ +:py:mod:`airflow.providers.fab.auth_manager.decorators` +======================================================= + +.. py:module:: airflow.providers.fab.auth_manager.decorators + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + auth/index.rst + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/fab_auth_manager/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/fab_auth_manager/index.rst.txt new file mode 100644 index 00000000000..d12bcc59183 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/fab_auth_manager/index.rst.txt @@ -0,0 +1,193 @@ +:py:mod:`airflow.providers.fab.auth_manager.fab_auth_manager` +============================================================= + +.. py:module:: airflow.providers.fab.auth_manager.fab_auth_manager + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager + + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.fab_auth_manager.get_parser + + + +.. py:class:: FabAuthManager(appbuilder) + + + Bases: :py:obj:`airflow.auth.managers.base_auth_manager.BaseAuthManager` + + Flask-AppBuilder auth manager. + + This auth manager is responsible for providing a backward compatible user management experience to users. + + .. py:method:: get_cli_commands() + :staticmethod: + + Vends CLI commands to be included in Airflow CLI. + + + .. py:method:: get_api_endpoints() + + Return API endpoint(s) definition for the auth manager. + + + .. py:method:: get_user_display_name() + + Return the user's display name associated to the user in session. + + + .. py:method:: get_user() + + Return the user associated to the user in session. + + + .. py:method:: init() + + Run operations when Airflow is initializing. + + + .. py:method:: is_logged_in() + + Return whether the user is logged in. + + + .. py:method:: is_authorized_configuration(*, method, details = None, user = None) + + Return whether the user is authorized to perform a given action on configuration. + + :param method: the method to perform + :param details: optional details about the configuration + :param user: the user to perform the action on. If not provided (or None), it uses the current user + + + .. py:method:: is_authorized_connection(*, method, details = None, user = None) + + Return whether the user is authorized to perform a given action on a connection. + + :param method: the method to perform + :param details: optional details about the connection + :param user: the user to perform the action on. If not provided (or None), it uses the current user + + + .. py:method:: is_authorized_dag(*, method, access_entity = None, details = None, user = None) + + Return whether the user is authorized to access the dag. + + There are multiple scenarios: + + 1. ``dag_access`` is not provided which means the user wants to access the DAG itself and not a sub + entity (e.g. DAG runs). + 2. ``dag_access`` is provided which means the user wants to access a sub entity of the DAG + (e.g. DAG runs). + + a. If ``method`` is GET, then check the user has READ permissions on the DAG and the sub entity. + b. Else, check the user has EDIT permissions on the DAG and ``method`` on the sub entity. However, + if no specific DAG is targeted, just check the sub entity. + + :param method: The method to authorize. + :param access_entity: The dag access entity. + :param details: The dag details. + :param user: The user. + + + .. py:method:: is_authorized_dataset(*, method, details = None, user = None) + + Return whether the user is authorized to perform a given action on a dataset. + + :param method: the method to perform + :param details: optional details about the dataset + :param user: the user to perform the action on. If not provided (or None), it uses the current user + + + .. py:method:: is_authorized_pool(*, method, details = None, user = None) + + Return whether the user is authorized to perform a given action on a pool. + + :param method: the method to perform + :param details: optional details about the pool + :param user: the user to perform the action on. If not provided (or None), it uses the current user + + + .. py:method:: is_authorized_variable(*, method, details = None, user = None) + + Return whether the user is authorized to perform a given action on a variable. + + :param method: the method to perform + :param details: optional details about the variable + :param user: the user to perform the action on. If not provided (or None), it uses the current user + + + .. py:method:: is_authorized_view(*, access_view, user = None) + + Return whether the user is authorized to access a read-only state of the installation. + + :param access_view: the specific read-only view/state the authorization request is about. + :param user: the user to perform the action on. If not provided (or None), it uses the current user + + + .. py:method:: is_authorized_custom_view(*, method, resource_name, user = None) + + Return whether the user is authorized to perform a given action on a custom view. + + A custom view can be a view defined as part of the auth manager. This view is then only available when + the auth manager is used as part of the environment. It can also be a view defined as part of a + plugin defined by a user. + + :param method: the method to perform + :param resource_name: the name of the resource + :param user: the user to perform the action on. If not provided (or None), it uses the current user + + + .. py:method:: get_permitted_dag_ids(*, methods = None, user=None, session = NEW_SESSION) + + Get readable or writable DAGs for user. + + By default, reads all the DAGs and check individually if the user has permissions to access the DAG. + Can lead to some poor performance. It is recommended to override this method in the auth manager + implementation to provide a more efficient implementation. + + :param methods: whether filter readable or writable + :param user: the current user + :param session: the session + + + .. py:method:: security_manager() + + Return the security manager specific to FAB. + + + .. py:method:: get_url_login(**kwargs) + + Return the login page url. + + + .. py:method:: get_url_logout() + + Return the logout page url. + + + .. py:method:: get_url_user_profile() + + Return the url to a page displaying info about the current user. + + + +.. py:function:: get_parser() + + Generate documentation; used by Sphinx argparse. + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/index.rst.txt new file mode 100644 index 00000000000..768271cb6bc --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/index.rst.txt @@ -0,0 +1,31 @@ +:py:mod:`airflow.providers.fab.auth_manager` +============================================ + +.. py:module:: airflow.providers.fab.auth_manager + + +Subpackages +----------- +.. toctree:: + :titlesonly: + :maxdepth: 3 + + api/index.rst + api_endpoints/index.rst + cli_commands/index.rst + decorators/index.rst + models/index.rst + openapi/index.rst + security_manager/index.rst + views/index.rst + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + fab_auth_manager/index.rst + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/models/anonymous_user/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/models/anonymous_user/index.rst.txt new file mode 100644 index 00000000000..0430c6f8d30 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/models/anonymous_user/index.rst.txt @@ -0,0 +1,33 @@ +:py:mod:`airflow.providers.fab.auth_manager.models.anonymous_user` +================================================================== + +.. py:module:: airflow.providers.fab.auth_manager.models.anonymous_user + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.models.anonymous_user.AnonymousUser + + + + +.. py:class:: AnonymousUser + + + Bases: :py:obj:`flask_login.AnonymousUserMixin`, :py:obj:`airflow.auth.managers.models.base_user.BaseUser` + + User object used when no active user is logged in. + + .. py:property:: roles + + + .. py:property:: perms + + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/models/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/models/index.rst.txt new file mode 100644 index 00000000000..b2b956f41e8 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/models/index.rst.txt @@ -0,0 +1,357 @@ +:py:mod:`airflow.providers.fab.auth_manager.models` +=================================================== + +.. py:module:: airflow.providers.fab.auth_manager.models + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + anonymous_user/index.rst + + +Package Contents +---------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.models.Action + airflow.providers.fab.auth_manager.models.Resource + airflow.providers.fab.auth_manager.models.Role + airflow.providers.fab.auth_manager.models.Permission + airflow.providers.fab.auth_manager.models.User + airflow.providers.fab.auth_manager.models.RegisterUser + + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.models.add_index_on_ab_user_username_postgres + airflow.providers.fab.auth_manager.models.add_index_on_ab_register_user_username_postgres + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.models.Identity + airflow.providers.fab.auth_manager.models.assoc_permission_role + airflow.providers.fab.auth_manager.models.assoc_user_role + + +.. py:data:: Identity + + + +.. py:class:: Action + + + Bases: :py:obj:`flask_appbuilder.models.sqla.Model` + + Represents permission actions such as `can_read`. + + .. py:attribute:: __tablename__ + :value: 'ab_permission' + + + + .. py:attribute:: id + + + + .. py:attribute:: name + + + + .. py:method:: __repr__() + + Return repr(self). + + + +.. py:class:: Resource + + + Bases: :py:obj:`flask_appbuilder.models.sqla.Model` + + Represents permission object such as `User` or `Dag`. + + .. py:attribute:: __tablename__ + :value: 'ab_view_menu' + + + + .. py:attribute:: id + + + + .. py:attribute:: name + + + + .. py:method:: __eq__(other) + + Return self==value. + + + .. py:method:: __neq__(other) + + + .. py:method:: __repr__() + + Return repr(self). + + + +.. py:data:: assoc_permission_role + + + +.. py:class:: Role + + + Bases: :py:obj:`flask_appbuilder.models.sqla.Model` + + Represents a user role to which permissions can be assigned. + + .. py:attribute:: __tablename__ + :value: 'ab_role' + + + + .. py:attribute:: id + + + + .. py:attribute:: name + + + + .. py:attribute:: permissions + + + + .. py:method:: __repr__() + + Return repr(self). + + + +.. py:class:: Permission + + + Bases: :py:obj:`flask_appbuilder.models.sqla.Model` + + Permission pair comprised of an Action + Resource combo. + + .. py:attribute:: __tablename__ + :value: 'ab_permission_view' + + + + .. py:attribute:: __table_args__ + :value: () + + + + .. py:attribute:: id + + + + .. py:attribute:: action_id + + + + .. py:attribute:: action + + + + .. py:attribute:: resource_id + + + + .. py:attribute:: resource + + + + .. py:method:: __repr__() + + Return repr(self). + + + +.. py:data:: assoc_user_role + + + +.. py:class:: User + + + Bases: :py:obj:`flask_appbuilder.models.sqla.Model`, :py:obj:`airflow.auth.managers.models.base_user.BaseUser` + + Represents an Airflow user which has roles assigned to it. + + .. py:property:: created_by_fk + + + .. py:property:: changed_by_fk + + + .. py:property:: is_authenticated + + + .. py:property:: is_active + + + .. py:property:: is_anonymous + + + .. py:property:: perms + + + .. py:attribute:: __tablename__ + :value: 'ab_user' + + + + .. py:attribute:: id + + + + .. py:attribute:: first_name + + + + .. py:attribute:: last_name + + + + .. py:attribute:: username + + + + .. py:attribute:: password + + + + .. py:attribute:: active + + + + .. py:attribute:: email + + + + .. py:attribute:: last_login + + + + .. py:attribute:: login_count + + + + .. py:attribute:: fail_login_count + + + + .. py:attribute:: roles + + + + .. py:attribute:: created_on + + + + .. py:attribute:: changed_on + + + + .. py:attribute:: created_by + + + + .. py:attribute:: changed_by + + + + .. py:method:: get_user_id() + :classmethod: + + + .. py:method:: get_id() + + + .. py:method:: get_name() + + + .. py:method:: get_full_name() + + + .. py:method:: __repr__() + + Return repr(self). + + + +.. py:class:: RegisterUser + + + Bases: :py:obj:`flask_appbuilder.models.sqla.Model` + + Represents a user registration. + + .. py:attribute:: __tablename__ + :value: 'ab_register_user' + + + + .. py:attribute:: id + + + + .. py:attribute:: first_name + + + + .. py:attribute:: last_name + + + + .. py:attribute:: username + + + + .. py:attribute:: password + + + + .. py:attribute:: email + + + + .. py:attribute:: registration_date + + + + .. py:attribute:: registration_hash + + + + +.. py:function:: add_index_on_ab_user_username_postgres(table, conn, **kw) + + +.. py:function:: add_index_on_ab_register_user_username_postgres(table, conn, **kw) + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/openapi/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/openapi/index.rst.txt new file mode 100644 index 00000000000..0e248128db1 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/openapi/index.rst.txt @@ -0,0 +1,6 @@ +:py:mod:`airflow.providers.fab.auth_manager.openapi` +==================================================== + +.. py:module:: airflow.providers.fab.auth_manager.openapi + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/security_manager/constants/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/security_manager/constants/index.rst.txt new file mode 100644 index 00000000000..2a2f7ae8160 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/security_manager/constants/index.rst.txt @@ -0,0 +1,13 @@ +:py:mod:`airflow.providers.fab.auth_manager.security_manager.constants` +======================================================================= + +.. py:module:: airflow.providers.fab.auth_manager.security_manager.constants + + +Module Contents +--------------- + +.. py:data:: EXISTING_ROLES + + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/security_manager/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/security_manager/index.rst.txt new file mode 100644 index 00000000000..6e7f308ba42 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/security_manager/index.rst.txt @@ -0,0 +1,16 @@ +:py:mod:`airflow.providers.fab.auth_manager.security_manager` +============================================================= + +.. py:module:: airflow.providers.fab.auth_manager.security_manager + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + constants/index.rst + override/index.rst + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/security_manager/override/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/security_manager/override/index.rst.txt new file mode 100644 index 00000000000..b5cc841cf00 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/security_manager/override/index.rst.txt @@ -0,0 +1,981 @@ +:py:mod:`airflow.providers.fab.auth_manager.security_manager.override` +====================================================================== + +.. py:module:: airflow.providers.fab.auth_manager.security_manager.override + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride + + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.security_manager.override.log + airflow.providers.fab.auth_manager.security_manager.override.MAX_NUM_DATABASE_USER_SESSIONS + + +.. py:data:: log + + + +.. py:data:: MAX_NUM_DATABASE_USER_SESSIONS + :value: 50000 + + + +.. py:class:: FabAirflowSecurityManagerOverride(appbuilder) + + + Bases: :py:obj:`airflow.www.security_manager.AirflowSecurityManagerV2` + + This security manager overrides the default AirflowSecurityManager security manager. + + This security manager is used only if the auth manager FabAuthManager is used. It defines everything in + the security manager that is needed for the FabAuthManager to work. Any operation specific to + the AirflowSecurityManager should be defined here instead of AirflowSecurityManager. + + :param appbuilder: The appbuilder. + + .. py:property:: get_session + + + .. py:property:: auth_type + + Get the auth type. + + + .. py:property:: is_auth_limited + :type: bool + + Is the auth rate limited. + + + .. py:property:: auth_rate_limit + :type: str + + Get the auth rate limit. + + + .. py:property:: auth_role_public + + Get the public role. + + + .. py:property:: oauth_providers + + Oauth providers. + + + .. py:property:: auth_ldap_tls_cacertdir + + LDAP TLS CA certificate directory. + + + .. py:property:: auth_ldap_tls_cacertfile + + LDAP TLS CA certificate file. + + + .. py:property:: auth_ldap_tls_certfile + + LDAP TLS certificate file. + + + .. py:property:: auth_ldap_tls_keyfile + + LDAP TLS key file. + + + .. py:property:: auth_ldap_allow_self_signed + + LDAP allow self signed. + + + .. py:property:: auth_ldap_tls_demand + + LDAP TLS demand. + + + .. py:property:: auth_ldap_server + + Get the LDAP server object. + + + .. py:property:: auth_ldap_use_tls + + Should LDAP use TLS. + + + .. py:property:: auth_ldap_bind_user + + LDAP bind user. + + + .. py:property:: auth_ldap_bind_password + + LDAP bind password. + + + .. py:property:: auth_ldap_search + + LDAP search object. + + + .. py:property:: auth_ldap_search_filter + + LDAP search filter. + + + .. py:property:: auth_ldap_uid_field + + LDAP UID field. + + + .. py:property:: auth_ldap_firstname_field + + LDAP first name field. + + + .. py:property:: auth_ldap_lastname_field + + LDAP last name field. + + + .. py:property:: auth_ldap_email_field + + LDAP email field. + + + .. py:property:: auth_ldap_append_domain + + LDAP append domain. + + + .. py:property:: auth_ldap_username_format + + LDAP username format. + + + .. py:property:: auth_ldap_group_field + :type: str + + LDAP group field. + + + .. py:property:: auth_roles_mapping + :type: dict[str, list[str]] + + The mapping of auth roles. + + + .. py:property:: auth_user_registration_role_jmespath + :type: str + + The JMESPATH role to use for user registration. + + + .. py:property:: auth_remote_user_env_var + :type: str + + + .. py:property:: api_login_allow_multiple_providers + + + .. py:property:: auth_username_ci + + Get the auth username for CI. + + + .. py:property:: auth_ldap_bind_first + + LDAP bind first. + + + .. py:property:: openid_providers + + Openid providers. + + + .. py:property:: auth_type_provider_name + + + .. py:property:: auth_user_registration + + Will user self registration be allowed. + + + .. py:property:: auth_user_registration_role + + The default user self registration role. + + + .. py:property:: auth_roles_sync_at_login + :type: bool + + Should roles be synced at login. + + + .. py:property:: auth_role_admin + + Get the admin role. + + + .. py:property:: oauth_whitelists + + + .. py:property:: builtin_roles + + Get the builtin roles. + + + .. py:attribute:: auth_view + + The obj instance for authentication view + + + .. py:attribute:: registeruser_view + + The obj instance for registering user view + + + .. py:attribute:: user_view + + The obj instance for user view + + + .. py:attribute:: user_model + + + + .. py:attribute:: role_model + + + + .. py:attribute:: action_model + + + + .. py:attribute:: resource_model + + + + .. py:attribute:: permission_model + + Views + + + .. py:attribute:: authdbview + + Override if you want your own Authentication DB view + + + .. py:attribute:: authldapview + + Override if you want your own Authentication LDAP view + + + .. py:attribute:: authoidview + + Override if you want your own Authentication OID view + + + .. py:attribute:: authoauthview + + Override if you want your own Authentication OAuth view + + + .. py:attribute:: authremoteuserview + + Override if you want your own Authentication REMOTE_USER view + + + .. py:attribute:: registeruserdbview + + Override if you want your own register user db view + + + .. py:attribute:: registeruseroidview + + Override if you want your own register user OpenID view + + + .. py:attribute:: registeruseroauthview + + Override if you want your own register user OAuth view + + + .. py:attribute:: actionmodelview + + + + .. py:attribute:: permissionmodelview + + + + .. py:attribute:: rolemodelview + + + + .. py:attribute:: registeruser_model + + + + .. py:attribute:: registerusermodelview + + + + .. py:attribute:: resourcemodelview + + + + .. py:attribute:: userdbmodelview + + + + .. py:attribute:: resetmypasswordview + + + + .. py:attribute:: resetpasswordview + + + + .. py:attribute:: userinfoeditview + + + + .. py:attribute:: userldapmodelview + + + + .. py:attribute:: useroauthmodelview + + + + .. py:attribute:: userremoteusermodelview + + + + .. py:attribute:: useroidmodelview + + + + .. py:attribute:: userstatschartview + + + + .. py:attribute:: jwt_manager + + Flask-JWT-Extended + + + .. py:attribute:: oid + + Flask-OpenID OpenID + + + .. py:attribute:: oauth + + + + .. py:attribute:: oauth_remotes + :type: dict[str, Any] + + Initialized (remote_app) providers dict {'provider_name', OBJ } + + + .. py:attribute:: oauth_user_info + + + + .. py:attribute:: oauth_allow_list + :type: dict[str, list] + + OAuth email allow list + + + .. py:attribute:: DAG_RESOURCES + + + + .. py:attribute:: VIEWER_PERMISSIONS + :value: [(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (),... + + + + .. py:attribute:: USER_PERMISSIONS + :value: [(), (), (), (), (), (), (), (), ()] + + + + .. py:attribute:: OP_PERMISSIONS + :value: [(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()] + + + + .. py:attribute:: ADMIN_PERMISSIONS + :value: [(), (), (), (), (), (), (), (), (), ()] + + + + .. py:attribute:: ROLE_CONFIGS + :type: list[dict[str, Any]] + + + + .. py:attribute:: DAG_ACTIONS + + + + .. py:method:: register_views() + + Register FAB auth manager related views. + + + .. py:method:: create_login_manager() + + Create the login manager. + + + .. py:method:: create_jwt_manager() + + Create the JWT manager. + + + .. py:method:: reset_password(userid, password) + + Change/Reset a user's password for auth db. + + Password will be hashed and saved. + + :param userid: the user id to reset the password + :param password: the clear text password to reset and save hashed on the db + + + .. py:method:: reset_user_sessions(user) + + + .. py:method:: load_user_jwt(_jwt_header, jwt_data) + + + .. py:method:: create_builtin_roles() + + Return FAB builtin roles. + + + .. py:method:: create_admin_standalone() + + Create an Admin user with a random password so that users can access airflow. + + + .. py:method:: create_db() + + Create the database. + + Creates admin and public roles if they don't exist. + + + .. py:method:: get_readable_dags(user) + + Get the DAGs readable by authenticated user. + + + .. py:method:: get_editable_dags(user) + + Get the DAGs editable by authenticated user. + + + .. py:method:: get_accessible_dags(user_actions, user, session = NEW_SESSION) + + + .. py:method:: get_accessible_dag_ids(user, user_actions = None, session = NEW_SESSION) + + + .. py:method:: get_readable_dag_ids(user=None) + :staticmethod: + + Get the DAG IDs readable by authenticated user. + + + .. py:method:: get_editable_dag_ids(user=None) + :staticmethod: + + Get the DAG IDs editable by authenticated user. + + + .. py:method:: can_access_some_dags(action, dag_id = None) + + Check if user has read or write access to some dags. + + + .. py:method:: get_all_permissions() + + Return all permissions as a set of tuples with the action and resource names. + + + .. py:method:: create_dag_specific_permissions() + + Add permissions to all DAGs. + + Creates 'can_read', 'can_edit', and 'can_delete' permissions for all + DAGs, along with any `access_control` permissions provided in them. + + This does iterate through ALL the DAGs, which can be slow. See `sync_perm_for_dag` + if you only need to sync a single DAG. + + + .. py:method:: prefixed_dag_id(dag_id) + + Return the permission name for a DAG id. + + + .. py:method:: is_dag_resource(resource_name) + + Determine if a resource belongs to a DAG or all DAGs. + + + .. py:method:: sync_perm_for_dag(dag_id, access_control = None) + + Sync permissions for given dag id. + + The dag id surely exists in our dag bag as only / refresh button or DagBag will call this function. + + :param dag_id: the ID of the DAG whose permissions should be updated + :param access_control: a dict where each key is a role name and + each value is a set() of action names (e.g., + {'can_read'} + :return: + + + .. py:method:: add_permissions_view(base_action_names, resource_name) + + Add an action on a resource to the backend. + + :param base_action_names: + list of permissions from view (all exposed methods): + 'can_add','can_edit' etc... + :param resource_name: + name of the resource to add + + + .. py:method:: add_permissions_menu(resource_name) + + Add menu_access to resource on permission_resource. + + :param resource_name: + The resource name + + + .. py:method:: security_cleanup(baseviews, menus) + + Cleanup all unused permissions from the database. + + :param baseviews: A list of BaseViews class + :param menus: Menu class + + + .. py:method:: sync_roles() + + Initialize default and custom roles with related permissions. + + 1. Init the default role(Admin, Viewer, User, Op, public) + with related permissions. + 2. Init the custom role(dag-user) with related permissions. + + + .. py:method:: create_perm_vm_for_all_dag() + + Create perm-vm if not exist and insert into FAB security model for all-dags. + + + .. py:method:: add_homepage_access_to_custom_roles() + + Add Website.can_read access to all custom roles. + + + .. py:method:: update_admin_permission() + + Add missing permissions to the table for admin. + + Admin should get all the permissions, except the dag permissions + because Admin already has Dags permission. + Add the missing ones to the table for admin. + + + .. py:method:: clean_perms() + + FAB leaves faulty permissions that need to be cleaned up. + + + .. py:method:: permission_exists_in_one_or_more_roles(resource_name, action_name, role_ids) + + Efficiently check if a certain permission exists on a list of role ids; used by `has_access`. + + :param resource_name: The view's name to check if exists on one of the roles + :param action_name: The permission name to check if exists + :param role_ids: a list of Role ids + :return: Boolean + + + .. py:method:: perms_include_action(perms, action_name) + + + .. py:method:: init_role(role_name, perms) + + Initialize the role with actions and related resources. + + :param role_name: + :param perms: + + + .. py:method:: bulk_sync_roles(roles) + + Sync the provided roles and permissions. + + + .. py:method:: sync_resource_permissions(perms = None) + + Populate resource-based permissions. + + + .. py:method:: update_role(role_id, name) + + Update a role in the database. + + + .. py:method:: add_role(name) + + Add a role in the database. + + + .. py:method:: find_role(name) + + Find a role in the database. + + :param name: the role name + + + .. py:method:: get_all_roles() + + + .. py:method:: delete_role(role_name) + + Delete the given Role. + + :param role_name: the name of a role in the ab_role table + + + .. py:method:: get_roles_from_keys(role_keys) + + Construct a list of FAB role objects, from a list of keys. + + NOTE: + - keys are things like: "LDAP group DNs" or "OAUTH group names" + - we use AUTH_ROLES_MAPPING to map from keys, to FAB role names + + :param role_keys: the list of FAB role keys + + + .. py:method:: get_public_role() + + + .. py:method:: add_user(username, first_name, last_name, email, role, password='', hashed_password='') + + Create a user. + + + .. py:method:: load_user(user_id) + + + .. py:method:: get_user_by_id(pk) + + + .. py:method:: count_users() + + Return the number of users in the database. + + + .. py:method:: add_register_user(username, first_name, last_name, email, password='', hashed_password='') + + Add a registration request for the user. + + :rtype : RegisterUser + + + .. py:method:: find_user(username=None, email=None) + + Find user by username or email. + + + .. py:method:: find_register_user(registration_hash) + + + .. py:method:: update_user(user) + + + .. py:method:: del_register_user(register_user) + + Delete registration object from database. + + :param register_user: RegisterUser object to delete + + + .. py:method:: get_all_users() + + + .. py:method:: update_user_auth_stat(user, success=True) + + Update user authentication stats. + + This is done upon successful/unsuccessful authentication attempts. + + :param user: + The identified (but possibly not successfully authenticated) user + model + :param success: + Defaults to true, if true increments login_count, updates + last_login, and resets fail_login_count to 0, if false increments + fail_login_count on user model. + + + .. py:method:: get_action(name) + + Get an existing action record. + + :param name: name + + + .. py:method:: create_action(name) + + Add an action to the backend, model action. + + :param name: + name of the action: 'can_add','can_edit' etc... + + + .. py:method:: delete_action(name) + + Delete a permission action. + + :param name: Name of action to delete (e.g. can_read). + + + .. py:method:: get_resource(name) + + Return a resource record by name, if it exists. + + :param name: Name of resource + + + .. py:method:: create_resource(name) + + Create a resource with the given name. + + :param name: The name of the resource to create created. + + + .. py:method:: get_all_resources() + + Get all existing resource records. + + + .. py:method:: delete_resource(name) + + Delete a Resource from the backend. + + :param name: + name of the resource + + + .. py:method:: get_permission(action_name, resource_name) + + Get a permission made with the given action->resource pair, if the permission already exists. + + :param action_name: Name of action + :param resource_name: Name of resource + + + .. py:method:: get_resource_permissions(resource) + + Retrieve permission pairs associated with a specific resource object. + + :param resource: Object representing a single resource. + + + .. py:method:: create_permission(action_name, resource_name) + + Add a permission on a resource to the backend. + + :param action_name: + name of the action to add: 'can_add','can_edit' etc... + :param resource_name: + name of the resource to add + + + .. py:method:: delete_permission(action_name, resource_name) + + Delete the permission linking an action->resource pair. + + Doesn't delete the underlying action or resource. + + :param action_name: Name of existing action + :param resource_name: Name of existing resource + + + .. py:method:: add_permission_to_role(role, permission) + + Add an existing permission pair to a role. + + :param role: The role about to get a new permission. + :param permission: The permission pair to add to a role. + + + .. py:method:: remove_permission_from_role(role, permission) + + Remove a permission pair from a role. + + :param role: User role containing permissions. + :param permission: Object representing resource-> action pair + + + .. py:method:: get_oid_identity_url(provider_name) + + Return the OIDC identity provider URL. + + + .. py:method:: get_user_roles(user=None) + :staticmethod: + + Get all the roles associated with the user. + + :param user: the ab_user in FAB model. + :return: a list of roles associated with the user. + + + .. py:method:: auth_user_ldap(username, password) + + Authenticate user with LDAP. + + NOTE: this depends on python-ldap module. + + :param username: the username + :param password: the password + + + .. py:method:: auth_user_db(username, password) + + Authenticate user, auth db style. + + :param username: + The username or registered email address + :param password: + The password, will be tested against hashed password on db + + + .. py:method:: oauth_user_info_getter(func) + + Get OAuth user info for all the providers. + + Receives provider and response return a dict with the information returned from the provider. + The returned user info dict should have its keys with the same name as the User Model. + + Use it like this an example for GitHub :: + + @appbuilder.sm.oauth_user_info_getter + def my_oauth_user_info(sm, provider, response=None): + if provider == "github": + me = sm.oauth_remotes[provider].get("user") + return {"username": me.data.get("login")} + return {} + + + .. py:method:: get_oauth_user_info(provider, resp) + + There are different OAuth APIs with different ways to retrieve user info. + + All providers have different ways to retrieve user info. + + + .. py:method:: oauth_token_getter() + :staticmethod: + + Get authentication (OAuth) token. + + + .. py:method:: check_authorization(perms = None, dag_id = None) + + Check the logged-in user has the specified permissions. + + + .. py:method:: set_oauth_session(provider, oauth_response) + + Set the current session with OAuth user secrets. + + + .. py:method:: get_oauth_token_key_name(provider) + + Return the token_key name for the oauth provider. + + If none is configured defaults to oauth_token + this is configured using OAUTH_PROVIDERS and token_key key. + + + .. py:method:: get_oauth_token_secret_name(provider) + + Get the ``token_secret`` name for the oauth provider. + + If none is configured, defaults to ``oauth_secret``. This is configured + using ``OAUTH_PROVIDERS`` and ``token_secret``. + + + .. py:method:: auth_user_oauth(userinfo) + + Authenticate user with OAuth. + + :userinfo: dict with user information + (keys are the same as User model columns) + + + .. py:method:: auth_user_oid(email) + + Openid user Authentication. + + :param email: user's email to authenticate + + + .. py:method:: auth_user_remote_user(username) + + REMOTE_USER user Authentication. + + :param username: user's username for remote auth + + + .. py:method:: get_user_menu_access(menu_names = None) + + + .. py:method:: ldap_extract_list(ldap_dict, field_name) + :staticmethod: + + + .. py:method:: ldap_extract(ldap_dict, field_name, fallback) + :staticmethod: + + + .. py:method:: filter_roles_by_perm_with_action(action_name, role_ids) + + Find roles with permission. + + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/index.rst.txt new file mode 100644 index 00000000000..235bcc1c42b --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/index.rst.txt @@ -0,0 +1,19 @@ +:py:mod:`airflow.providers.fab.auth_manager.views` +================================================== + +.. py:module:: airflow.providers.fab.auth_manager.views + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + permissions/index.rst + roles_list/index.rst + user/index.rst + user_edit/index.rst + user_stats/index.rst + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/permissions/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/permissions/index.rst.txt new file mode 100644 index 00000000000..e2266f5b054 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/permissions/index.rst.txt @@ -0,0 +1,161 @@ +:py:mod:`airflow.providers.fab.auth_manager.views.permissions` +============================================================== + +.. py:module:: airflow.providers.fab.auth_manager.views.permissions + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.views.permissions.ActionModelView + airflow.providers.fab.auth_manager.views.permissions.PermissionPairModelView + airflow.providers.fab.auth_manager.views.permissions.ResourceModelView + + + + +.. py:class:: ActionModelView(**kwargs) + + + Bases: :py:obj:`flask_appbuilder.security.views.PermissionModelView` + + Customize permission names for FAB's builtin PermissionModelView. + + .. py:attribute:: class_permission_name + + + + .. py:attribute:: route_base + :value: '/actions' + + + + .. py:attribute:: method_permission_name + + + + .. py:attribute:: base_permissions + + + + .. py:attribute:: list_title + + + + .. py:attribute:: show_title + + + + .. py:attribute:: add_title + + + + .. py:attribute:: edit_title + + + + .. py:attribute:: label_columns + + + + +.. py:class:: PermissionPairModelView(**kwargs) + + + Bases: :py:obj:`flask_appbuilder.security.views.PermissionViewModelView` + + Customize permission names for FAB's builtin PermissionViewModelView. + + .. py:attribute:: class_permission_name + + + + .. py:attribute:: route_base + :value: '/permissions' + + + + .. py:attribute:: method_permission_name + + + + .. py:attribute:: base_permissions + + + + .. py:attribute:: list_title + + + + .. py:attribute:: show_title + + + + .. py:attribute:: add_title + + + + .. py:attribute:: edit_title + + + + .. py:attribute:: label_columns + + + + .. py:attribute:: list_columns + :value: ['action', 'resource'] + + + + +.. py:class:: ResourceModelView(**kwargs) + + + Bases: :py:obj:`flask_appbuilder.security.views.ViewMenuModelView` + + Customize permission names for FAB's builtin ViewMenuModelView. + + .. py:attribute:: class_permission_name + + + + .. py:attribute:: route_base + :value: '/resources' + + + + .. py:attribute:: method_permission_name + + + + .. py:attribute:: base_permissions + + + + .. py:attribute:: list_title + + + + .. py:attribute:: show_title + + + + .. py:attribute:: add_title + + + + .. py:attribute:: edit_title + + + + .. py:attribute:: label_columns + + + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/roles_list/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/roles_list/index.rst.txt new file mode 100644 index 00000000000..729379b24fb --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/roles_list/index.rst.txt @@ -0,0 +1,39 @@ +:py:mod:`airflow.providers.fab.auth_manager.views.roles_list` +============================================================= + +.. py:module:: airflow.providers.fab.auth_manager.views.roles_list + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.views.roles_list.CustomRoleModelView + + + + +.. py:class:: CustomRoleModelView(**kwargs) + + + Bases: :py:obj:`flask_appbuilder.security.views.RoleModelView` + + Customize permission names for FAB's builtin RoleModelView. + + .. py:attribute:: class_permission_name + + + + .. py:attribute:: method_permission_name + + + + .. py:attribute:: base_permissions + + + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/user/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/user/index.rst.txt new file mode 100644 index 00000000000..cf1665e14c8 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/user/index.rst.txt @@ -0,0 +1,126 @@ +:py:mod:`airflow.providers.fab.auth_manager.views.user` +======================================================= + +.. py:module:: airflow.providers.fab.auth_manager.views.user + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.views.user.MultiResourceUserMixin + airflow.providers.fab.auth_manager.views.user.CustomUserLDAPModelView + airflow.providers.fab.auth_manager.views.user.CustomUserOAuthModelView + airflow.providers.fab.auth_manager.views.user.CustomUserOIDModelView + airflow.providers.fab.auth_manager.views.user.CustomUserRemoteUserModelView + airflow.providers.fab.auth_manager.views.user.CustomUserDBModelView + + + + +.. py:class:: MultiResourceUserMixin + + + Remaps UserModelView permissions to new resources and actions. + + .. py:property:: class_permission_name + + Returns appropriate permission name depending on request method name. + + + .. py:attribute:: class_permission_name_mapping + + + + .. py:attribute:: method_permission_name + + + + .. py:attribute:: base_permissions + + + + .. py:method:: show(pk) + + + +.. py:class:: CustomUserLDAPModelView(**kwargs) + + + Bases: :py:obj:`MultiResourceUserMixin`, :py:obj:`flask_appbuilder.security.views.UserLDAPModelView` + + Customize permission names for FAB's builtin UserLDAPModelView. + + .. py:attribute:: class_permission_name_mapping + + + + .. py:attribute:: method_permission_name + + + + .. py:attribute:: base_permissions + + + + +.. py:class:: CustomUserOAuthModelView(**kwargs) + + + Bases: :py:obj:`MultiResourceUserMixin`, :py:obj:`flask_appbuilder.security.views.UserOAuthModelView` + + Customize permission names for FAB's builtin UserOAuthModelView. + + +.. py:class:: CustomUserOIDModelView(**kwargs) + + + Bases: :py:obj:`MultiResourceUserMixin`, :py:obj:`flask_appbuilder.security.views.UserOIDModelView` + + Customize permission names for FAB's builtin UserOIDModelView. + + +.. py:class:: CustomUserRemoteUserModelView(**kwargs) + + + Bases: :py:obj:`MultiResourceUserMixin`, :py:obj:`flask_appbuilder.security.views.UserRemoteUserModelView` + + Customize permission names for FAB's builtin UserRemoteUserModelView. + + .. py:attribute:: class_permission_name_mapping + + + + .. py:attribute:: method_permission_name + + + + .. py:attribute:: base_permissions + + + + +.. py:class:: CustomUserDBModelView(**kwargs) + + + Bases: :py:obj:`MultiResourceUserMixin`, :py:obj:`flask_appbuilder.security.views.UserDBModelView` + + Customize permission names for FAB's builtin UserDBModelView. + + .. py:attribute:: class_permission_name_mapping + + + + .. py:attribute:: method_permission_name + + + + .. py:attribute:: base_permissions + + + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/user_edit/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/user_edit/index.rst.txt new file mode 100644 index 00000000000..6b6fc8570f3 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/user_edit/index.rst.txt @@ -0,0 +1,86 @@ +:py:mod:`airflow.providers.fab.auth_manager.views.user_edit` +============================================================ + +.. py:module:: airflow.providers.fab.auth_manager.views.user_edit + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.views.user_edit.CustomUserInfoEditView + airflow.providers.fab.auth_manager.views.user_edit.CustomResetMyPasswordView + airflow.providers.fab.auth_manager.views.user_edit.CustomResetPasswordView + + + + +.. py:class:: CustomUserInfoEditView + + + Bases: :py:obj:`flask_appbuilder.security.views.UserInfoEditView` + + Customize permission names for FAB's builtin UserInfoEditView. + + .. py:attribute:: class_permission_name + + + + .. py:attribute:: route_base + :value: '/userinfoeditview' + + + + .. py:attribute:: method_permission_name + + + + .. py:attribute:: base_permissions + + + + +.. py:class:: CustomResetMyPasswordView + + + Bases: :py:obj:`flask_appbuilder.security.views.ResetMyPasswordView` + + Customize permission names for FAB's builtin ResetMyPasswordView. + + .. py:attribute:: class_permission_name + + + + .. py:attribute:: method_permission_name + + + + .. py:attribute:: base_permissions + + + + +.. py:class:: CustomResetPasswordView + + + Bases: :py:obj:`flask_appbuilder.security.views.ResetPasswordView` + + Customize permission names for FAB's builtin ResetPasswordView. + + .. py:attribute:: class_permission_name + + + + .. py:attribute:: method_permission_name + + + + .. py:attribute:: base_permissions + + + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/user_stats/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/user_stats/index.rst.txt new file mode 100644 index 00000000000..82133e0fb41 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/auth_manager/views/user_stats/index.rst.txt @@ -0,0 +1,44 @@ +:py:mod:`airflow.providers.fab.auth_manager.views.user_stats` +============================================================= + +.. py:module:: airflow.providers.fab.auth_manager.views.user_stats + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + airflow.providers.fab.auth_manager.views.user_stats.CustomUserStatsChartView + + + + +.. py:class:: CustomUserStatsChartView(**kwargs) + + + Bases: :py:obj:`flask_appbuilder.security.views.UserStatsChartView` + + Customize permission names for FAB's builtin UserStatsChartView. + + .. py:attribute:: class_permission_name + + + + .. py:attribute:: route_base + :value: '/userstatschartview' + + + + .. py:attribute:: method_permission_name + + + + .. py:attribute:: base_permissions + + + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/index.rst.txt new file mode 100644 index 00000000000..a4a9d0aad0a --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/_api/airflow/providers/fab/index.rst.txt @@ -0,0 +1,23 @@ +:py:mod:`airflow.providers.fab` +=============================== + +.. py:module:: airflow.providers.fab + + +Subpackages +----------- +.. toctree:: + :titlesonly: + :maxdepth: 3 + + auth_manager/index.rst + + +Package Contents +---------------- + +.. py:data:: __version__ + :value: '1.0.4' + + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/auth-manager/access-control.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/auth-manager/access-control.rst.txt new file mode 100644 index 00000000000..98424360d22 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/auth-manager/access-control.rst.txt @@ -0,0 +1,332 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +Access Control +============== + +Access Control of Airflow Webserver UI is handled by Flask AppBuilder (FAB). +Please read its related `security document `_ +regarding its security model. + +.. spelling:word-list:: + clearTaskInstances + dagRuns + dagSources + eventLogs + importErrors + taskInstances + xcomEntries + +Default Roles +''''''''''''' +Airflow ships with a set of roles by default: Admin, User, Op, Viewer, and Public. +By default, only ``Admin`` users can configure/alter permissions for roles. However, +it is recommended that these default roles remain unaltered, and instead ``Admin`` users +create new roles with the desired permissions if changes are necessary. + +Public +^^^^^^ +``Public`` users (anonymous) don't have any permissions. + +Viewer +^^^^^^ +``Viewer`` users have limited read permissions: + +.. exampleinclude:: /../../airflow/providers/fab/auth_manager/security_manager/override.py + :language: python + :start-after: [START security_viewer_perms] + :end-before: [END security_viewer_perms] + +User +^^^^ +``User`` users have ``Viewer`` permissions plus additional permissions: + +.. exampleinclude:: /../../airflow/providers/fab/auth_manager/security_manager/override.py + :language: python + :start-after: [START security_user_perms] + :end-before: [END security_user_perms] + +Op +^^ +``Op`` users have ``User`` permissions plus additional permissions: + +.. exampleinclude:: /../../airflow/providers/fab/auth_manager/security_manager/override.py + :language: python + :start-after: [START security_op_perms] + :end-before: [END security_op_perms] + +Admin +^^^^^ +``Admin`` users have all possible permissions, including granting or revoking permissions from +other users. ``Admin`` users have ``Op`` permission plus additional permissions: + +.. exampleinclude:: /../../airflow/providers/fab/auth_manager/security_manager/override.py + :language: python + :start-after: [START security_admin_perms] + :end-before: [END security_admin_perms] + +Custom Roles +''''''''''''' + +DAG Level Role +^^^^^^^^^^^^^^ +``Admin`` can create a set of roles which are only allowed to view a certain set of DAGs. This is called DAG level access. Each DAG defined in the DAG model table +is treated as a ``View`` which has two permissions associated with it (``can_read`` and ``can_edit``. ``can_dag_read`` and ``can_dag_edit`` are deprecated since 2.0.0). +There is a special view called ``DAGs`` (it was called ``all_dags`` in versions 1.10.*) which +allows the role to access all the DAGs. The default ``Admin``, ``Viewer``, ``User``, ``Op`` roles can all access ``DAGs`` view. + +.. image:: /img/add-role.png +.. image:: /img/new-role.png + +The image shows the creation of a role which can only write to +``example_python_operator``. You can also create roles via the CLI +using the ``airflow roles create`` command, e.g.: + +.. code-block:: bash + + airflow roles create Role1 Role2 + +And we could assign the given role to a new user using the ``airflow +users add-role`` CLI command. + + +Permissions +''''''''''' + +Resource-Based permissions +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Starting with version 2.0, permissions are based on individual resources and a small subset of actions on those +resources. Resources match standard Airflow concepts, such as ``Dag``, ``DagRun``, ``Task``, and +``Connection``. Actions include ``can_create``, ``can_read``, ``can_edit``, and ``can_delete``. + +Permissions (each consistent of a resource + action pair) are then added to roles. + +**To access an endpoint, the user needs all permissions assigned to that endpoint** + +There are five default roles: Public, Viewer, User, Op, and Admin. Each one has the permissions of the preceding role, as well as additional permissions. + +DAG-level permissions +^^^^^^^^^^^^^^^^^^^^^ + +For DAG-level permissions exclusively, access can be controlled at the level of all DAGs or individual DAG objects. This includes ``DAGs.can_read``, ``DAGs.can_edit``, and ``DAGs.can_delete``. When these permissions are listed, access is granted to users who either have the listed permission or the same permission for the specific DAG being acted upon. For individual DAGs, the resource name is ``DAG:`` + the DAG ID. + +For example, if a user is trying to view DAG information for the ``example_dag_id``, and the endpoint requires ``DAGs.can_read`` access, access will be granted if the user has either ``DAGs.can_read`` or ``DAG:example_dag_id.can_read`` access. + +================================================================================== ====== ================================================================= ============ +Stable API Permissions +------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +Endpoint Method Permissions Minimum Role +================================================================================== ====== ================================================================= ============ +/config GET Configurations.can_read Op +/connections GET Connections.can_read Op +/connections POST Connections.can_create Op +/connections/{connection_id} DELETE Connections.can_delete Op +/connections/{connection_id} PATCH Connections.can_edit Op +/connections/{connection_id} GET Connections.can_read Op +/dagSources/{file_token} GET DAG Code.can_read Viewer +/dags GET DAGs.can_read Viewer +/dags/{dag_id} GET DAGs.can_read Viewer +/dags/{dag_id} PATCH DAGs.can_edit User +/dags/{dag_id}/clearTaskInstances POST DAGs.can_edit, DAG Runs.can_read, Task Instances.can_edit User +/dags/{dag_id}/details GET DAGs.can_read Viewer +/dags/{dag_id}/tasks GET DAGs.can_read, Task Instances.can_read Viewer +/dags/{dag_id}/tasks/{task_id} GET DAGs.can_read, Task Instances.can_read Viewer +/dags/{dag_id}/dagRuns GET DAGs.can_read, DAG Runs.can_read Viewer +/dags/{dag_id}/dagRuns POST DAGs.can_edit, DAG Runs.can_create User +/dags/{dag_id}/dagRuns/{dag_run_id} DELETE DAGs.can_edit, DAG Runs.can_delete User +/dags/{dag_id}/dagRuns/{dag_run_id} GET DAGs.can_read, DAG Runs.can_read Viewer +/dags/~/dagRuns/list POST DAGs.can_edit, DAG Runs.can_read User +/datasets GET Datasets.can_read Viewer +/datasets/{uri} GET Datasets.can_read Viewer +/datasets/events GET Datasets.can_read Viewer +/eventLogs GET Audit Logs.can_read Viewer +/eventLogs/{event_log_id} GET Audit Logs.can_read Viewer +/importErrors GET ImportError.can_read Viewer +/importErrors/{import_error_id} GET ImportError.can_read Viewer +/health GET None Public +/version GET None Public +/pools GET Pools.can_read Op +/pools POST Pools.can_create Op +/pools/{pool_name} DELETE Pools.can_delete Op +/pools/{pool_name} GET Pools.can_read Op +/pools/{pool_name} PATCH Pools.can_edit Op +/providers GET Providers.can_read Op +/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances GET DAGs.can_read, DAG Runs.can_read, Task Instances.can_read Viewer +/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id} GET DAGs.can_read, DAG Runs.can_read, Task Instances.can_read Viewer +/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/links GET DAGs.can_read, DAG Runs.can_read, Task Instances.can_read Viewer +/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/logs/{task_try_number} GET DAGs.can_read, DAG Runs.can_read, Task Instances.can_read Viewer +/dags/~/dagRuns/~/taskInstances/list POST DAGs.can_edit, DAG Runs.can_read, Task Instances.can_read User +/variables GET Variables.can_read Op +/variables POST Variables.can_create Op +/variables/{variable_key} DELETE Variables.can_delete Op +/variables/{variable_key} GET Variables.can_read Op +/variables/{variable_key} PATCH Variables.can_edit Op +/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/xcomEntries GET DAGs.can_read, DAG Runs.can_read, Viewer + Task Instances.can_read, XComs.can_read +/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/xcomEntries/{xcom_key} GET DAGs.can_read, DAG Runs.can_read, Viewer + Task Instances.can_read, XComs.can_read +/users GET Users.can_read Admin +/users POST Users.can_create Admin +/users/{username} GET Users.can_read Admin +/users/{username} PATCH Users.can_edit Admin +/users/{username} DELETE Users.can_delete Admin +/roles GET Roles.can_read Admin +/roles POST Roles.can_create Admin +/roles/{role_name} GET Roles.can_read Admin +/roles/{role_name} PATCH Roles.can_edit Admin +/roles/{role_name} DELETE Roles.can_delete Admin +/permissions GET Permission Views.can_read Admin +================================================================================== ====== ================================================================= ============ + + +====================================== ======================================================================= ============ +Website Permissions +-------------------------------------- ------------------------------------------------------------------------------------ +Action Permissions Minimum Role +====================================== ======================================================================= ============ +Access homepage Website.can_read Viewer +Show Browse menu Browse.menu_access Viewer +Show DAGs menu DAGs.menu_access Viewer +Get DAG stats DAGs.can_read, DAG Runs.can_read Viewer +Show Task Instances menu Task Instances.menu_access Viewer +Get Task stats DAGs.can_read, DAG Runs.can_read, Task Instances.can_read Viewer +Get last DAG runs DAGs.can_read, DAG Runs.can_read Viewer +Get DAG code DAGs.can_read, DAG Code.can_read Viewer +Get DAG details DAGs.can_read, DAG Runs.can_read Viewer +Show DAG Dependencies menu DAG Dependencies.menu_access Viewer +Get DAG Dependencies DAG Dependencies.can_read Viewer +Get rendered DAG DAGs.can_read, Task Instances.can_read Viewer +Get Logs with metadata DAGs.can_read, Task Instances.can_read, Task Logs.can_read Viewer +Get Log DAGs.can_read, Task Instances.can_read, Task Logs.can_read Viewer +Redirect to external Log DAGs.can_read, Task Instances.can_read, Task Logs.can_read Viewer +Get Task DAGs.can_read, Task Instances.can_read Viewer +Show XCom menu XComs.menu_access Op +Get XCom DAGs.can_read, Task Instances.can_read, XComs.can_read Viewer +Create XCom XComs.can_create Op +Delete XCom XComs.can_delete Op +Triggers Task Instance DAGs.can_edit, Task Instances.can_create User +Delete DAG DAGs.can_delete User +Show DAG Runs menu DAG Runs.menu_access Viewer +Trigger DAG run DAGs.can_edit, DAG Runs.can_create User +Clear DAG DAGs.can_edit, Task Instances.can_delete User +Clear DAG Run DAGs.can_edit, Task Instances.can_delete User +Mark DAG as blocked DAGS.can_edit, DAG Runs.can_read User +Mark DAG Run as failed DAGS.can_edit, DAG Runs.can_edit User +Mark DAG Run as success DAGS.can_edit, DAG Runs.can_edit User +Mark Task as failed DAGs.can_edit, Task Instances.can_edit User +Mark Task as success DAGs.can_edit, Task Instances.can_edit User +Get DAG as tree DAGs.can_read, Task Instances.can_read, Viewer + Task Logs.can_read +Get DAG as graph DAGs.can_read, Task Instances.can_read, Viewer + Task Logs.can_read +Get DAG as duration graph DAGs.can_read, Task Instances.can_read Viewer +Show all tries DAGs.can_read, Task Instances.can_read Viewer +Show landing times DAGs.can_read, Task Instances.can_read Viewer +Toggle DAG paused status DAGs.can_edit User +Show Gantt Chart DAGs.can_read, Task Instances.can_read Viewer +Get external links DAGs.can_read, Task Instances.can_read Viewer +Show Task Instances DAGs.can_read, Task Instances.can_read Viewer +Show Configurations menu Configurations.menu_access Op +Show Configs Configurations.can_read Viewer +Delete multiple records DAGs.can_edit User +Set Task Instance as running DAGs.can_edit User +Set Task Instance as failed DAGs.can_edit User +Set Task Instance as success DAGs.can_edit User +Set Task Instance as up_for_retry DAGs.can_edit User +Autocomplete DAGs.can_read Viewer +Show Dataset menu Datasets.menu_access Viewer +Show Datasets Datasets.can_read Viewer +Show Docs menu Docs.menu_access Viewer +Show Documentation menu Documentation.menu_access Viewer +Show Jobs menu Jobs.menu_access Viewer +Show Audit Log Audit Logs.menu_access Viewer +Reset Password My Password.can_read, My Password.can_edit Viewer +Show Permissions menu Permission Views.menu_access Admin +List Permissions Permission Views.can_read Admin +Get My Profile My Profile.can_read Viewer +Update My Profile My Profile.can_edit Viewer +List Logs Audit Logs.can_read Viewer +List Jobs Jobs.can_read Viewer +Show SLA Misses menu SLA Misses.menu_access Viewer +List SLA Misses SLA Misses.can_read Viewer +List Plugins Plugins.can_read Viewer +Show Plugins menu Plugins.menu_access Viewer +Show Providers menu Providers.menu_access Op +List Providers Providers.can_read Op +List Task Reschedules Task Reschedules.can_read Admin +Show Triggers menu Triggers.menu_access Admin +List Triggers Triggers.can_read Admin +Show Admin menu Admin.menu_access Viewer +Show Connections menu Connections.menu_access Op +Show Pools menu Pools.menu_access Viewer +Show Variables menu Variables.menu_access Op +Show Roles menu Roles.menu_access Admin +List Roles Roles.can_read Admin +Create Roles Roles.can_create Admin +Update Roles Roles.can_edit Admin +Delete Roles Roles.can_delete Admin +Show Users menu Users.menu_access Admin +Create Users Users.can_create Admin +Update Users Users.can_edit Admin +Delete Users Users.can_delete Admin +Reset user Passwords Passwords.can_edit, Passwords.can_read Admin +====================================== ======================================================================= ============ + +These DAG-level controls can be set directly through the UI / CLI, or encoded in the dags themselves through the access_control arg. + +Order of precedence for DAG-level permissions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Since DAG-level access control can be configured in multiple places, conflicts are inevitable and a clear resolution strategy is required. As a result, +Airflow considers the ``access_control`` argument supplied on a DAG itself to be completely authoritative if present, which has a few effects: + +Setting ``access_control`` on a DAG will overwrite any previously existing DAG-level permissions if it is any value other than ``None``: + +.. code-block:: python + + DAG( + dag_id="example_fine_grained_access", + start_date=pendulum.datetime(2021, 1, 1, tz="UTC"), + access_control={ + "Viewer": {"can_edit", "can_read", "can_delete"}, + }, + ) + +This also means that setting ``access_control={}`` will wipe any existing DAG-level permissions for a given DAG from the DB: + +.. code-block:: python + + DAG( + dag_id="example_no_fine_grained_access", + start_date=pendulum.datetime(2021, 1, 1, tz="UTC"), + access_control={}, + ) + +Conversely, removing the access_control block from a DAG altogether (or setting it to ``None``) won't make any changes and can leave dangling permissions. + +.. code-block:: python + + DAG( + dag_id="example_indifferent_to_fine_grained_access", + start_date=pendulum.datetime(2021, 1, 1, tz="UTC"), + ) + +In the case that there is no ``access_control`` defined on the DAG itself, Airflow will defer to existing permissions defined in the DB, which +may have been set through the UI, CLI or by previous access_control args on the DAG in question. + +In all cases, system-wide roles such as ``Can edit on DAG`` take precedence over dag-level access controls, such that they can be considered ``Can edit on DAG: *`` diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/auth-manager/api-authentication.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/auth-manager/api-authentication.rst.txt new file mode 100644 index 00000000000..7ab50e52c18 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/auth-manager/api-authentication.rst.txt @@ -0,0 +1,137 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +API Authentication +================== + +Authentication for the API is handled separately to the Web Authentication. The default is to +check the user session: + +.. code-block:: ini + + [api] + auth_backends = airflow.api.auth.backend.session + +.. versionchanged:: 1.10.11 + + In Airflow <1.10.11, the default setting was to allow all API requests without authentication, but this + posed security risks for if the Webserver is publicly accessible. + +.. versionchanged:: 2.3.0 + + In Airflow <2.3.0 this setting was ``auth_backend`` and allowed only one + value. In 2.3.0 it was changed to support multiple backends that are tried + in turn. + +If you want to check which authentication backends are currently set, you can use ``airflow config get-value api auth_backends`` +command as in the example below. + +.. code-block:: console + + $ airflow config get-value api auth_backends + airflow.api.auth.backend.basic_auth + +Disable authentication +'''''''''''''''''''''' + +If you wish to have the experimental API work, and aware of the risks of enabling this without authentication +(or if you have your own authentication layer in front of Airflow) you can set the following in ``airflow.cfg``: + +.. code-block:: ini + + [api] + auth_backends = airflow.api.auth.backend.default + +.. note:: + + You can only disable authentication for experimental API, not the stable REST API. + +See :doc:`apache-airflow:administration-and-deployment/modules_management` for details on how Python and Airflow manage modules. + +Kerberos authentication +''''''''''''''''''''''' + +Kerberos authentication is currently supported for the API. + +To enable Kerberos authentication, set the following in the configuration: + +.. code-block:: ini + + [api] + auth_backends = airflow.api.auth.backend.kerberos_auth + + [kerberos] + keytab = + +The Kerberos service is configured as ``airflow/fully.qualified.domainname@REALM``. Make sure this +principal exists in the keytab file. + +You have to make sure to name your users with the kerberos full username/realm in order to make it +works. This means that your user name should be ``user_name@KERBEROS-REALM``. + +Basic authentication +'''''''''''''''''''' + +`Basic username password authentication `_ is currently +supported for the API. This works for users created through LDAP login or +within Airflow Metadata DB using password. + +To enable basic authentication, set the following in the configuration: + +.. code-block:: ini + + [api] + auth_backends = airflow.api.auth.backend.basic_auth + +Username and password needs to be base64 encoded and send through the +``Authorization`` HTTP header in the following format: + +.. code-block:: text + + Authorization: Basic Base64(username:password) + +Here is a sample curl command you can use to validate the setup: + +.. code-block:: bash + + ENDPOINT_URL="http://localhost:8080/" + curl -X GET \ + --user "username:password" \ + "${ENDPOINT_URL}/api/v1/pools" + +Note, you can still enable this setting to allow API access through username +password credential even though Airflow webserver might be using another +authentication method. Under this setup, only users created through LDAP or +``airflow users create`` command will be able to pass the API authentication. + +Roll your own API authentication +'''''''''''''''''''''''''''''''' + +Each auth backend is defined as a new Python module. It must have 2 defined methods: + +* ``init_app(app: Flask)`` - function invoked when creating a flask application, which allows you to add a new view. +* ``requires_authentication(fn: Callable)`` - a decorator that allows arbitrary code execution before and after or instead of a view function. + +and may have one of the following to support API client authorizations used by :ref:`remote mode for CLI `: + +* function ``create_client_session() -> requests.Session`` +* attribute ``CLIENT_AUTH: tuple[str, str] | requests.auth.AuthBase | None`` + +After writing your backend module, provide the fully qualified module name in the ``auth_backends`` key in the ``[api]`` +section of ``airflow.cfg``. + +Additional options to your auth backend can be configured in ``airflow.cfg``, as a new option. diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/auth-manager/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/auth-manager/index.rst.txt new file mode 100644 index 00000000000..8d19ff56498 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/auth-manager/index.rst.txt @@ -0,0 +1,32 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +Flask AppBuilder (FAB) auth manager +=================================== + +FAB auth (for authentication/authorization) manager is the auth manager that comes by default with Airflow. This auth manager defines the user authentication and user authorization by default in Airflow. +The backend used to store all entities used by the FAB auth manager is the Airflow database: :doc:`apache-airflow:database-erd-ref`. + +.. image:: ../img/diagram_fab_auth_manager_airflow_architecture.png + +Follow the below topics as well to understand other aspects of FAB auth manager: + +.. toctree:: + :maxdepth: 1 + :glob: + + * diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/auth-manager/webserver-authentication.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/auth-manager/webserver-authentication.rst.txt new file mode 100644 index 00000000000..feabad33a80 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/auth-manager/webserver-authentication.rst.txt @@ -0,0 +1,231 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +Webserver authentication +======================== + +By default, Airflow requires users to specify a password prior to login. You can use the +following CLI commands to create an account: + +.. code-block:: bash + + # create an admin user + airflow users create \ + --username admin \ + --firstname Peter \ + --lastname Parker \ + --role Admin \ + --email spiderman@superhero.org + +To deactivate the authentication and allow users to be identified as Anonymous, the following entry +in ``$AIRFLOW_HOME/webserver_config.py`` needs to be set with the desired role that the Anonymous +user will have by default: + +.. code-block:: ini + + AUTH_ROLE_PUBLIC = 'Admin' + +Be sure to checkout :doc:`apache-airflow:security/api` for securing the API. + +.. note:: + + Airflow uses the config parser of Python. This config parser interpolates + '%'-signs. Make sure escape any ``%`` signs in your config file (but not + environment variables) as ``%%``, otherwise Airflow might leak these + passwords on a config parser exception to a log. + +Password +'''''''' + +One of the simplest mechanisms for authentication is requiring users to specify a password before logging in. + +Please use command line interface ``airflow users create`` to create accounts, or do that in the UI. + +Other Methods +''''''''''''' + +Since Airflow 2.0, the default UI is the Flask App Builder RBAC. A ``webserver_config.py`` configuration file +is automatically generated and can be used to configure the Airflow to support authentication +methods like OAuth, OpenID, LDAP, REMOTE_USER. It should be noted that due to the limitation of Flask AppBuilder +and Authlib, only a selection of OAuth2 providers is supported. This list includes ``github``, ``githublocal``, ``twitter``, +``linkedin``, ``google``, ``azure``, ``openshift``, ``okta``, ``keycloak`` and ``keycloak_before_17``. + +The default authentication option described in the :ref:`Web Authentication ` section is related +with the following entry in the ``$AIRFLOW_HOME/webserver_config.py``. + +.. code-block:: ini + + AUTH_TYPE = AUTH_DB + +A WSGI middleware could be used to manage very specific forms of authentication +(e.g. `SPNEGO `_) +and leverage the REMOTE_USER method: + +.. code-block:: python + + from typing import Any, Callable + + from flask import current_app + from flask_appbuilder.const import AUTH_REMOTE_USER + + + class CustomMiddleware: + def __init__(self, wsgi_app: Callable) -> None: + self.wsgi_app = wsgi_app + + def __call__(self, environ: dict, start_response: Callable) -> Any: + # Custom authenticating logic here + # ... + environ["REMOTE_USER"] = "username" + return self.wsgi_app(environ, start_response) + + + current_app.wsgi_app = CustomMiddleware(current_app.wsgi_app) + + AUTH_TYPE = AUTH_REMOTE_USER + +Another way to create users is in the UI login page, allowing user self registration through a "Register" button. +The following entries in the ``$AIRFLOW_HOME/webserver_config.py`` can be edited to make it possible: + +.. code-block:: ini + + AUTH_USER_REGISTRATION = True + AUTH_USER_REGISTRATION_ROLE = "Desired Role For The Self Registered User" + RECAPTCHA_PRIVATE_KEY = 'private_key' + RECAPTCHA_PUBLIC_KEY = 'public_key' + + MAIL_SERVER = 'smtp.gmail.com' + MAIL_USE_TLS = True + MAIL_USERNAME = 'yourappemail@gmail.com' + MAIL_PASSWORD = 'passwordformail' + MAIL_DEFAULT_SENDER = 'sender@gmail.com' + +The package ``Flask-Mail`` needs to be installed through pip to allow user self registration since it is a +feature provided by the framework Flask-AppBuilder. + +To support authentication through a third-party provider, the ``AUTH_TYPE`` entry needs to be updated with the +desired option like OAuth, OpenID, LDAP, and the lines with references for the chosen option need to have +the comments removed and configured in the ``$AIRFLOW_HOME/webserver_config.py``. + +For more details, please refer to +`Security section of FAB documentation `_. + +Example using team based Authorization with GitHub OAuth +'''''''''''''''''''''''''''''''''''''''''''''''''''''''' +There are a few steps required in order to use team-based authorization with GitHub OAuth. + +* configure OAuth through the FAB config in webserver_config.py +* create a custom security manager class and supply it to FAB in webserver_config.py +* map the roles returned by your security manager class to roles that FAB understands. + +Here is an example of what you might have in your webserver_config.py: + +.. code-block:: python + + from airflow.auth.managers.fab.security_manager.override import FabAirflowSecurityManagerOverride + from flask_appbuilder.security.manager import AUTH_OAUTH + import os + + AUTH_TYPE = AUTH_OAUTH + AUTH_ROLES_SYNC_AT_LOGIN = True # Checks roles on every login + AUTH_USER_REGISTRATION = True # allow users who are not already in the FAB DB to register + + AUTH_ROLES_MAPPING = { + "Viewer": ["Viewer"], + "Admin": ["Admin"], + } + # If you wish, you can add multiple OAuth providers. + OAUTH_PROVIDERS = [ + { + "name": "github", + "icon": "fa-github", + "token_key": "access_token", + "remote_app": { + "client_id": os.getenv("OAUTH_APP_ID"), + "client_secret": os.getenv("OAUTH_APP_SECRET"), + "api_base_url": "https://api.github.com", + "client_kwargs": {"scope": "read:user, read:org"}, + "access_token_url": "https://github.com/login/oauth/access_token", + "authorize_url": "https://github.com/login/oauth/authorize", + "request_token_url": None, + }, + }, + ] + + + class CustomSecurityManager(FabAirflowSecurityManagerOverride): + pass + + + # Make sure to replace this with your own implementation of AirflowSecurityManager class + SECURITY_MANAGER_CLASS = CustomSecurityManager + +Here is an example of defining a custom security manager. +This class must be available in Python's path, and could be defined in +webserver_config.py itself if you wish. + +.. code-block:: python + + from airflow.auth.managers.fab.security_manager.override import FabAirflowSecurityManagerOverride + import logging + from typing import Any, List, Union + import os + + log = logging.getLogger(__name__) + log.setLevel(os.getenv("AIRFLOW__LOGGING__FAB_LOGGING_LEVEL", "INFO")) + + FAB_ADMIN_ROLE = "Admin" + FAB_VIEWER_ROLE = "Viewer" + FAB_PUBLIC_ROLE = "Public" # The "Public" role is given no permissions + TEAM_ID_A_FROM_GITHUB = 123 # Replace these with real team IDs for your org + TEAM_ID_B_FROM_GITHUB = 456 # Replace these with real team IDs for your org + + + def team_parser(team_payload: dict[str, Any]) -> list[int]: + # Parse the team payload from GitHub however you want here. + return [team["id"] for team in team_payload] + + + def map_roles(team_list: list[int]) -> list[str]: + # Associate the team IDs with Roles here. + # The expected output is a list of roles that FAB will use to Authorize the user. + + team_role_map = { + TEAM_ID_A_FROM_GITHUB: FAB_ADMIN_ROLE, + TEAM_ID_B_FROM_GITHUB: FAB_VIEWER_ROLE, + } + return list(set(team_role_map.get(team, FAB_PUBLIC_ROLE) for team in team_list)) + + + class GithubTeamAuthorizer(FabAirflowSecurityManagerOverride): + # In this example, the oauth provider == 'github'. + # If you ever want to support other providers, see how it is done here: + # https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/security/manager.py#L550 + def get_oauth_user_info(self, provider: str, resp: Any) -> dict[str, Union[str, list[str]]]: + # Creates the user info payload from Github. + # The user previously allowed your app to act on their behalf, + # so now we can query the user and teams endpoints for their data. + # Username and team membership are added to the payload and returned to FAB. + + remote_app = self.appbuilder.sm.oauth_remotes[provider] + me = remote_app.get("user") + user_data = me.json() + team_data = remote_app.get("user/teams") + teams = team_parser(team_data.json()) + roles = map_roles(teams) + log.debug(f"User info from Github: {user_data}\nTeam info from Github: {teams}") + return {"username": "github_" + user_data.get("login"), "role_keys": roles} diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/changelog.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/changelog.rst.txt new file mode 100644 index 00000000000..c6bdcaa11e7 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/changelog.rst.txt @@ -0,0 +1,25 @@ + + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + .. NOTE! THIS FILE IS AUTOMATICALLY GENERATED AND WILL BE + OVERWRITTEN WHEN PREPARING PACKAGES. + + .. IF YOU WANT TO MODIFY THIS FILE, YOU SHOULD MODIFY THE TEMPLATE + `PROVIDER_CHANGELOG_TEMPLATE.rst.jinja2` IN the `dev/breeze/src/airflow_breeze/templates` DIRECTORY + +.. include:: ../../airflow/providers/fab/CHANGELOG.rst diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/cli-ref.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/cli-ref.rst.txt new file mode 100644 index 00000000000..bd980f8a1ee --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/cli-ref.rst.txt @@ -0,0 +1,29 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +FAB CLI Commands +================ + +.. note:: + The CLI commands below are sourced from the FAB provider by Airflow 2.9.0+. + Previously, they were part of core Airflow, so if you are using Airflow below 2.9.0 please see + the core Airflow documentation for the list of CLI commands and parameters available. + +.. argparse:: + :module: airflow.providers.fab.auth_manager.fab_auth_manager + :func: get_parser + :prog: airflow diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/commits.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/commits.rst.txt new file mode 100644 index 00000000000..d274636e300 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/commits.rst.txt @@ -0,0 +1,135 @@ + + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + .. NOTE! THIS FILE IS AUTOMATICALLY GENERATED AND WILL BE + OVERWRITTEN WHEN PREPARING PACKAGES. + + .. IF YOU WANT TO MODIFY THIS FILE, YOU SHOULD MODIFY THE TEMPLATE + `PROVIDER_COMMITS_TEMPLATE.rst.jinja2` IN the `dev/breeze/src/airflow_breeze/templates` DIRECTORY + + .. THE REMAINDER OF THE FILE IS AUTOMATICALLY GENERATED. IT WILL BE OVERWRITTEN AT RELEASE TIME! + +Package apache-airflow-providers-fab +------------------------------------------------------ + +`Flask App Builder `__ + + +This is detailed commit list of changes for versions provider package: ``fab``. +For high-level changelog, see :doc:`package information including changelog `. + + + +1.0.4 +..... + +Latest change: 2024-04-15 + +================================================================================================= =========== ============================================================================ +Commit Committed Subject +================================================================================================= =========== ============================================================================ +`f8104325b7 `_ 2024-04-15 ``Activate RUF019 that checks for unnecessary key check (#38950)`` +`c3bb80da93 `_ 2024-04-12 ``Remove button for reset my password when we have reset password (#38957)`` +================================================================================================= =========== ============================================================================ + +1.0.3 +..... + +Latest change: 2024-04-10 + +================================================================================================= =========== ================================================================== +Commit Committed Subject +================================================================================================= =========== ================================================================== +`5fa80b6aea `_ 2024-04-10 ``Prepare docs 1st wave (RC1) April 2024 (#38863)`` +`53cd7173b4 `_ 2024-04-10 ``Fix azure authentication when no email is set (#38872)`` +`6d3d2075ae `_ 2024-04-07 ``fix: try002 for provider fab (#38801)`` +`e700f4150a `_ 2024-03-30 ``Rename 'allowed_filter_attrs' to 'allowed_sort_attrs' (#38626)`` +================================================================================================= =========== ================================================================== + +1.0.2 +..... + +Latest change: 2024-03-25 + +================================================================================================= =========== =================================================================================== +Commit Committed Subject +================================================================================================= =========== =================================================================================== +`256911aa62 `_ 2024-03-25 ``Prepare fab provider RC1 (#38451)`` +`7776e9154d `_ 2024-03-20 ``Upgrade FAB to 4.4.1 (#38319)`` +`0a74928894 `_ 2024-03-18 ``Bump ruff to 0.3.3 (#38240)`` +`2e35854a05 `_ 2024-03-15 ``Make the method 'BaseAuthManager.is_authorized_custom_view' abstract (#37915)`` +`c0b849ad2b `_ 2024-03-11 ``Avoid use of 'assert' outside of the tests (#37718)`` +`c6f34394c4 `_ 2024-03-11 ``Improve suffix handling for provider-generated dependencies (#38029)`` +`3f52790d42 `_ 2024-03-06 ``Resolve G004: Logging statement uses f-string (#37873)`` +`fd4dfd875d `_ 2024-03-06 ``Remove useless methods from security manager (#37889)`` +`3211a5fcea `_ 2024-03-06 ``Use 'next' when redirecting (#37904)`` +`89e7f3e7bd `_ 2024-03-05 ``Add "MENU" permission in auth manager (#37881)`` +`30f7b2abe6 `_ 2024-03-04 ``Avoid to use too broad 'noqa' (#37862)`` +`9b17ff3aa3 `_ 2024-02-26 ``Add post endpoint for dataset events (#37570)`` +`16d2671704 `_ 2024-02-20 ``Add "queuedEvent" endpoint to get/delete DatasetDagRunQueue (#37176)`` +`79603f9302 `_ 2024-02-19 ``Add swagger path to FAB Auth manager and Internal API (#37525)`` +`f2ea8a3e17 `_ 2024-02-19 ``Revoking audit_log permission from all users except admin (#37501)`` +`68e20aa702 `_ 2024-02-17 ``Enable the 'Is Active?' flag by default in user view (#37507)`` +`5a0be392e6 `_ 2024-02-16 ``Add comment about versions updated by release manager (#37488)`` +`4551c592b2 `_ 2024-02-14 ``Until we release 2.9.0, we keep airflow >= 2.9.0.dev0 for FAB provider (#37421)`` +================================================================================================= =========== =================================================================================== + +1.0.1 +..... + +Latest change: 2024-02-14 + +================================================================================================= =========== ========================================================================================= +Commit Committed Subject +================================================================================================= =========== ========================================================================================= +`54a400fcb6 `_ 2024-02-14 ``Mark FAB provider as ready (#37362)`` +`ec97a07197 `_ 2024-02-13 ``standardize get_app appbuilder usage (#37397)`` +`28f94f8891 `_ 2024-02-10 ``Move 'IMPORT_ERROR' from DAG related permissions to view related permissions (#37292)`` +`00ed46769e `_ 2024-02-09 ``D401 support in fab provider (#37283)`` +`e99cfbbd51 `_ 2024-02-07 ``Upgrade to FAB 4.3.11 (#37233)`` +`daa2bceba1 `_ 2024-02-07 ``Use 'next_url' instead of 'next' (#37225)`` +`dec2662190 `_ 2024-01-30 ``feat: Switch all class, functions, methods deprecations to decorators (#36876)`` +`0fce3b6047 `_ 2024-01-28 ``Add "airflow users reset-password" command (#37044)`` +`ce246c0ed8 `_ 2024-01-26 ``fix for role and permission count in export (#36589)`` +`18d2498e44 `_ 2024-01-11 ``Generate doc for fab CLI commands (#36672)`` +`c439ab87c4 `_ 2024-01-10 ``Standardize airflow build process and switch to Hatchling build backend (#36537)`` +`28cad70223 `_ 2024-01-03 ``Move config related to FAB auth manager to FAB provider (#36232)`` +`2093b6f3b9 `_ 2024-01-03 ``Fix security manager inheritance in fab provider (#36538)`` +`dec78ab3f1 `_ 2024-01-03 ``Remove MSSQL support form Airflow core (#36514)`` +`e28627f6a5 `_ 2024-01-02 ``Cli export / import roles including permissions (#36347)`` +`6937ae7647 `_ 2023-12-30 ``Speed up autocompletion of Breeze by simplifying provider state (#36499)`` +`83bdc297ce `_ 2023-12-30 ``added cli command to list auth managers under 'airflow providers' (#36445)`` +`341d5b747d `_ 2023-12-23 ``Add feture of "not-ready" provider. (#36391)`` +================================================================================================= =========== ========================================================================================= + +1.0.0 +..... + +Latest change: 2023-12-23 + +================================================================================================= =========== ================================================================================== +Commit Committed Subject +================================================================================================= =========== ================================================================================== +`b15d5578da `_ 2023-12-23 ``Re-apply updated version numbers to 2nd wave of providers in December (#36380)`` +`2be7149598 `_ 2023-12-21 ``fix inheritance checking of security manager in FabAuthManager (#36343)`` +`e9ba37bb58 `_ 2023-12-17 ``Add code snippet formatting in docstrings via Ruff (#36262)`` +`f7f7183617 `_ 2023-12-17 ``Update permission docs (#36120)`` +`4d96a9a3a1 `_ 2023-12-13 ``Remove dependency of 'Connexion' from auth manager interface (#36209)`` +`357355ac09 `_ 2023-12-11 ``Remove 'is_authorized_cluster_activity' from auth manager (#36175)`` +`1eca667e5f `_ 2023-12-11 ``Create FAB provider and move FAB auth manager in it (#35926)`` +================================================================================================= =========== ================================================================================== diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/configurations-ref.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/configurations-ref.rst.txt new file mode 100644 index 00000000000..5885c9d91b6 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/configurations-ref.rst.txt @@ -0,0 +1,18 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +.. include:: ../exts/includes/providers-configurations-ref.rst diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/index.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/index.rst.txt new file mode 100644 index 00000000000..b19aeab3dd3 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/index.rst.txt @@ -0,0 +1,107 @@ + +.. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +``apache-airflow-providers-fab`` +================================ + + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: Basics + + Home + Changelog + Security + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: Guides + + Auth manager + +.. toctree:: + :hidden: + :caption: References + + Stable REST API + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: References + + Configuration + CLI + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: Resources + + Python API <_api/airflow/providers/fab/index> + PyPI Repository + Installing from sources + +.. THE REMAINDER OF THE FILE IS AUTOMATICALLY GENERATED. IT WILL BE OVERWRITTEN AT RELEASE TIME! + + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: Commits + + Detailed list of commits + + +apache-airflow-providers-fab package +------------------------------------------------------ + +`Flask App Builder `__ + + +Release: 1.0.4 + +Provider package +---------------- + +This package is for the ``fab`` provider. +All classes for this package are included in the ``airflow.providers.fab`` python package. + +Installation +------------ + +You can install this package on top of an existing Airflow 2 installation via +``pip install apache-airflow-providers-fab``. +For the minimum Airflow version supported, see ``Requirements`` below. + +Requirements +------------ + +The minimum Apache Airflow version supported by this provider package is ``2.9.0``. + +==================== ================== +PIP package Version required +==================== ================== +``apache-airflow`` ``>=2.9.0`` +``flask`` ``>=2.2,<2.3`` +``flask-appbuilder`` ``==4.4.1`` +``flask-login`` ``>=0.6.2`` +``google-re2`` ``>=1.0`` +==================== ================== diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/installing-providers-from-sources.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/installing-providers-from-sources.rst.txt new file mode 100644 index 00000000000..b4e730f4ff2 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/installing-providers-from-sources.rst.txt @@ -0,0 +1,18 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +.. include:: ../exts/includes/installing-providers-from-sources.rst diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/security.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/security.rst.txt new file mode 100644 index 00000000000..afa13dac6fc --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/security.rst.txt @@ -0,0 +1,18 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +.. include:: ../exts/includes/security.rst diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/stable-rest-api-ref.rst.txt b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/stable-rest-api-ref.rst.txt new file mode 100644 index 00000000000..673b88cc35b --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sources/stable-rest-api-ref.rst.txt @@ -0,0 +1,23 @@ + + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +REST API Reference +================== + +It's a stub file. It will be converted automatically during the build process +to the valid documentation by the Sphinx plugin. See: /docs/conf.py diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css b/docs-archive/apache-airflow-providers-fab/1.0.4/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css new file mode 100644 index 00000000000..eb19f698afc --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css @@ -0,0 +1 @@ +.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative}details.sd-dropdown .sd-summary-title{font-weight:700;padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary{list-style:none;padding:1em}details.sd-dropdown summary .sd-octicon.no-title{vertical-align:middle}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown summary::-webkit-details-marker{display:none}details.sd-dropdown summary:focus{outline:none}details.sd-dropdown .sd-summary-icon{margin-right:.5em}details.sd-dropdown .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary:hover .sd-summary-up svg,details.sd-dropdown summary:hover .sd-summary-down svg{opacity:1;transform:scale(1.1)}details.sd-dropdown .sd-summary-up svg,details.sd-dropdown .sd-summary-down svg{display:block;opacity:.6}details.sd-dropdown .sd-summary-up,details.sd-dropdown .sd-summary-down{pointer-events:none;position:absolute;right:1em;top:1em}details.sd-dropdown[open]>.sd-summary-title .sd-summary-down{visibility:hidden}details.sd-dropdown:not([open])>.sd-summary-title .sd-summary-up{visibility:hidden}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #0071bc;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0060a0;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem} diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_sphinx_design_static/design-tabs.js b/docs-archive/apache-airflow-providers-fab/1.0.4/_sphinx_design_static/design-tabs.js new file mode 100644 index 00000000000..36b38cf0d91 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_sphinx_design_static/design-tabs.js @@ -0,0 +1,27 @@ +var sd_labels_by_text = {}; + +function ready() { + const li = document.getElementsByClassName("sd-tab-label"); + for (const label of li) { + syncId = label.getAttribute("data-sync-id"); + if (syncId) { + label.onclick = onLabelClick; + if (!sd_labels_by_text[syncId]) { + sd_labels_by_text[syncId] = []; + } + sd_labels_by_text[syncId].push(label); + } + } +} + +function onLabelClick() { + // Activate other inputs with the same sync id. + syncId = this.getAttribute("data-sync-id"); + for (label of sd_labels_by_text[syncId]) { + if (label === this) continue; + label.previousElementSibling.checked = true; + } + window.localStorage.setItem("sphinx-design-last-tab", syncId); +} + +document.addEventListener("DOMContentLoaded", ready, false); diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_static/_gen/css/main-custom.min.css b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/_gen/css/main-custom.min.css new file mode 100644 index 00000000000..46f1de59325 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/_gen/css/main-custom.min.css @@ -0,0 +1 @@ +@charset "UTF-8";@import "https://fonts.googleapis.com/css?family=Rubik:500&display=swap";@import "https://fonts.googleapis.com/css?family=Roboto:400,400i,500,700&display=swap";@import "https://fonts.googleapis.com/css?family=Roboto+Mono:400,700&display=swap";.header__large--cerulean-blue{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#017cee}.header__large--shamrock{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#00ad46}.header__large--bright-sky-blue{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#0cb6ff}.header__large--melon{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#ff7557}.header__large--vermillion{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#e43921}.header__large--aqua{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#11e1ee}.header__large--shamrock-green{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#04d659}.header__large--aqua-blue{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#00c7d4}.header__large--white{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#fff}.header__large--brownish-grey{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#707070}.header__large--very-light-pink{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#cbcbcb}.header__large--slate-grey{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#636365}.header__large--greyish-brown,#header-canvas .text-area--header{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#51504f}.header__medium--cerulean-blue{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#017cee}.header__medium--shamrock{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#00ad46}.header__medium--bright-sky-blue{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#0cb6ff}.header__medium--melon{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#ff7557}.header__medium--vermillion{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#e43921}.header__medium--aqua{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#11e1ee}.header__medium--shamrock-green{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#04d659}.header__medium--aqua-blue{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#00c7d4}.header__medium--white{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#fff}.header__medium--brownish-grey{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#707070}.header__medium--very-light-pink{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#cbcbcb}.header__medium--slate-grey{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#636365}.header__medium--greyish-brown,.page-header{font-family:rubik,sans-serif;font-weight:500;font-size:60px;line-height:1.23;color:#51504f}.header__small--cerulean-blue{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#017cee}.header__small--shamrock{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#00ad46}.header__small--bright-sky-blue{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#0cb6ff}.header__small--melon{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#ff7557}.header__small--vermillion{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#e43921}.header__small--aqua{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#11e1ee}.header__small--shamrock-green{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#04d659}.header__small--aqua-blue{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#00c7d4}.header__small--white{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#fff}.header__small--brownish-grey{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#707070}.header__small--very-light-pink{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#cbcbcb}.header__small--slate-grey{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#636365}.header__small--greyish-brown,.blogpost-content__metadata--title,.community--header-join,.community--committers-header{font-family:rubik,sans-serif;font-weight:500;font-size:48px;line-height:1.25;color:#51504f}.header__xsmall--cerulean-blue{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#017cee}.header__xsmall--shamrock{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#00ad46}.header__xsmall--bright-sky-blue{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#0cb6ff}.header__xsmall--melon{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#ff7557}.header__xsmall--vermillion{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#e43921}.header__xsmall--aqua{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#11e1ee}.header__xsmall--shamrock-green{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#04d659}.header__xsmall--aqua-blue{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#00c7d4}.header__xsmall--white{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#fff}.header__xsmall--brownish-grey{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#707070}.header__xsmall--very-light-pink{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#cbcbcb}.header__xsmall--slate-grey{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#636365}.header__xsmall--greyish-brown,.feature-item--header,.text-with-icon-item--header{font-family:rubik,sans-serif;font-weight:500;font-size:36px;line-height:1.22;color:#51504f}.subtitle__large--cerulean-blue,.box-event__meetup--location{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#017cee}.subtitle__large--shamrock{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#00ad46}.subtitle__large--bright-sky-blue{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#0cb6ff}.subtitle__large--melon{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#ff7557}.subtitle__large--vermillion{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#e43921}.subtitle__large--aqua{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#11e1ee}.subtitle__large--shamrock-green{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#04d659}.subtitle__large--aqua-blue{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#00c7d4}.subtitle__large--white{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#fff}.subtitle__large--brownish-grey,.quote--text,.page-subtitle,.blogpost-content__metadata--description,#header-canvas .text-area--subheader{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#707070}.subtitle__large--very-light-pink{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#cbcbcb}.subtitle__large--slate-grey{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#636365}.subtitle__large--greyish-brown,.box-event__blogpost--header,.markdown-content h1,.markdown-content h2,.markdown-content h3,.markdown-content h4,.markdown-content h5{font-family:roboto,sans-serif;font-weight:500;font-size:24px;line-height:1.5;color:#51504f}.subtitle__medium--cerulean-blue,ol.counter-blue li::before{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#017cee}.subtitle__medium--shamrock{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#00ad46}.subtitle__medium--bright-sky-blue{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#0cb6ff}.subtitle__medium--melon{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#ff7557}.subtitle__medium--vermillion{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#e43921}.subtitle__medium--aqua{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#11e1ee}.subtitle__medium--shamrock-green{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#04d659}.subtitle__medium--aqua-blue{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#00c7d4}.subtitle__medium--white{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#fff}.subtitle__medium--brownish-grey,.box-event__integration--name{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#707070}.subtitle__medium--very-light-pink{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#cbcbcb}.subtitle__medium--slate-grey{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#636365}.subtitle__medium--greyish-brown,.roadmap .td-sidebar nav>ul>li>a{font-family:roboto,sans-serif;font-weight:500;font-size:18px;line-height:1.33;color:#51504f}.bodytext__medium--cerulean-blue,.box-event__blogpost--author,.box-event__meetup--next-meetup,.tag,.new-entry--link,.blogpost-content__metadata--author{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#017cee}.bodytext__medium--shamrock{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#00ad46}.bodytext__medium--bright-sky-blue{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#0cb6ff}.bodytext__medium--melon{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#ff7557}.bodytext__medium--vermillion{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#e43921}.bodytext__medium--aqua{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#11e1ee}.bodytext__medium--shamrock-green{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#04d659}.bodytext__medium--aqua-blue{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#00c7d4}.bodytext__medium--white,footer .footer-section span{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#fff}.bodytext__medium--brownish-grey,ol.counter-blue li,ul.ticks-blue li,.box-event__blogpost--description,.box-event__blogpost--date,.box-event__case-study--quote,.box-event__meetup--members,.markdown-content p,.markdown-content span,.feature-item--text,.text-with-icon-item--text,.video-list__item .video-list__item--title,.blogpost-content__metadata--date,.install--description,.roadmap .breadcrumb-item a,.roadmap .td-sidebar li>a,.sidebar__version-selector a{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#707070}.bodytext__medium--very-light-pink{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#cbcbcb}.bodytext__medium--slate-grey{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#636365}.bodytext__medium--greyish-brown,.box-event__committer--nick,.quote--author,.list-link,.install__accordions-content--header,.navbar__text-link{font-family:roboto,sans-serif;font-weight:400;font-size:16px;line-height:1.63;color:#51504f}.bodytext__mobile--cerulean-blue{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#017cee}.bodytext__mobile--shamrock{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#00ad46}.bodytext__mobile--bright-sky-blue{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#0cb6ff}.bodytext__mobile--melon{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#ff7557}.bodytext__mobile--vermillion{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#e43921}.bodytext__mobile--aqua{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#11e1ee}.bodytext__mobile--shamrock-green{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#04d659}.bodytext__mobile--aqua-blue{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#00c7d4}.bodytext__mobile--white{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#fff}.bodytext__mobile--brownish-grey{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#707070}.bodytext__mobile--very-light-pink{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#cbcbcb}.bodytext__mobile--slate-grey{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#636365}.bodytext__mobile--greyish-brown{font-family:roboto,sans-serif;font-weight:400;font-size:14px;line-height:1.57;color:#51504f}.bodytext__small--cerulean-blue{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#017cee}.bodytext__small--shamrock{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#00ad46}.bodytext__small--bright-sky-blue{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#0cb6ff}.bodytext__small--melon{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#ff7557}.bodytext__small--vermillion{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#e43921}.bodytext__small--aqua{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#11e1ee}.bodytext__small--shamrock-green{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#04d659}.bodytext__small--aqua-blue{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#00c7d4}.bodytext__small--white{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#fff}.bodytext__small--brownish-grey{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#707070}.bodytext__small--very-light-pink{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#cbcbcb}.bodytext__small--slate-grey{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#636365}.bodytext__small--greyish-brown{font-family:roboto,sans-serif;font-weight:400;font-size:12px;line-height:1.33;color:#51504f}.bodytext__xsmall--cerulean-blue{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#017cee}.bodytext__xsmall--shamrock{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#00ad46}.bodytext__xsmall--bright-sky-blue{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#0cb6ff}.bodytext__xsmall--melon{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#ff7557}.bodytext__xsmall--vermillion{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#e43921}.bodytext__xsmall--aqua{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#11e1ee}.bodytext__xsmall--shamrock-green{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#04d659}.bodytext__xsmall--aqua-blue{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#00c7d4}.bodytext__xsmall--white{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#fff}.bodytext__xsmall--brownish-grey{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#707070}.bodytext__xsmall--very-light-pink{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#cbcbcb}.bodytext__xsmall--slate-grey{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#636365}.bodytext__xsmall--greyish-brown{font-family:roboto,sans-serif;font-weight:400;font-size:10px;line-height:2.6;color:#51504f}.monotext--cerulean-blue{font-family:roboto mono,monospace;color:#017cee;font-size:14px;line-height:1.71}.monotext--shamrock{font-family:roboto mono,monospace;color:#00ad46;font-size:14px;line-height:1.71}.monotext--bright-sky-blue{font-family:roboto mono,monospace;color:#0cb6ff;font-size:14px;line-height:1.71}.monotext--melon{font-family:roboto mono,monospace;color:#ff7557;font-size:14px;line-height:1.71}.monotext--vermillion{font-family:roboto mono,monospace;color:#e43921;font-size:14px;line-height:1.71}.monotext--aqua{font-family:roboto mono,monospace;color:#11e1ee;font-size:14px;line-height:1.71}.monotext--shamrock-green{font-family:roboto mono,monospace;color:#04d659;font-size:14px;line-height:1.71}.monotext--aqua-blue{font-family:roboto mono,monospace;color:#00c7d4;font-size:14px;line-height:1.71}.monotext--white{font-family:roboto mono,monospace;color:#fff;font-size:14px;line-height:1.71}.monotext--brownish-grey,.markdown-content pre span,pre span{font-family:roboto mono,monospace;color:#707070;font-size:14px;line-height:1.71}.monotext--very-light-pink{font-family:roboto mono,monospace;color:#cbcbcb;font-size:14px;line-height:1.71}.monotext--slate-grey{font-family:roboto mono,monospace;color:#636365;font-size:14px;line-height:1.71}.monotext--greyish-brown{font-family:roboto mono,monospace;color:#51504f;font-size:14px;line-height:1.71}.font-weight-normal{font-weight:400!important}.font-weight-500{font-weight:500!important}.font-weight-bold{font-weight:700!important}details.accordion{padding:40px 30px;border-bottom:solid 1px #cbcbcb;-webkit-transition:ease 1s;-o-transition:ease 1s;transition:ease 1s}details.accordion:first-of-type{border-top:solid 1px #cbcbcb}details.accordion summary{position:relative;display:block;outline:none}details.accordion summary::-webkit-details-marker{display:none}details.accordion .accordion__summary-content{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;max-width:750px;margin-right:40px}details.accordion .accordion__summary-content--icon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;width:60px;margin-right:42px}details.accordion .accordion__summary-content--header{margin-bottom:20px}details.accordion .accordion__arrow{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;position:absolute;width:36px;height:36px;top:0;right:0;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;border:solid 1px #017cee;border-radius:50%}details.accordion .accordion__arrow svg{-webkit-transition:ease-out .2s;-o-transition:ease-out .2s;transition:ease-out .2s}details.accordion[open] .accordion__arrow svg{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}details.accordion .accordion__content{margin-top:30px;margin-right:36px}details.accordion .accordion__content.indented{margin-left:102px}@media(max-width:1280px){details.accordion{padding:30px 0}details.accordion .accordion__summary-content--icon{-webkit-box-align:unset;-webkit-align-items:unset;-ms-flex-align:unset;align-items:unset;margin-right:20px;margin-top:28px}details.accordion .accordion__arrow{width:28px;height:28px;top:5px}details.accordion .accordion__content.indented{margin-left:80px}details.accordion .accordion__content ol.counter-blue{margin-left:-38px!important}}button{cursor:pointer;border:1px solid;border-radius:5px;padding:9px 29px;-webkit-transition:all ease-out .2s;-o-transition:all ease-out .2s;transition:all ease-out .2s}button:disabled{cursor:not-allowed}button.btn-filled{border-color:#017cee;background-color:#017cee}button.btn-filled:hover{border-color:#0cb6ff;background-color:#0cb6ff}button.btn-with-icon{padding:14px 20px}button.btn-with-icon svg{height:30px;width:auto;padding-right:15px}button.btn-with-icon span{display:inline-block;line-height:30px;vertical-align:middle}button.btn-hollow{background-color:#fff}button.btn-hollow.btn-blue{color:#017cee;border-color:#017cee}button.btn-hollow.btn-blue:disabled{color:#cbcbcb;border-color:#cbcbcb}button.btn-hollow.btn-blue:hover:enabled{color:#fff;background-color:#017cee}button.btn-hollow.btn-brown{border-color:#cbcbcb}button.btn-hollow.btn-brown:hover{background-color:#51504f;border-color:#51504f}button.btn-hollow.btn-brown:hover span{color:#fff}button.btn-hollow.btn-brown:hover svg path{fill:#fff}button.with-box-shadow{-webkit-box-shadow:0 2px 6px 0 rgba(0,0,0,.12);box-shadow:0 2px 6px 0 rgba(0,0,0,.12)}@media(max-width:1280px){button{padding:4px 17px}}ol.counter-blue,ul.ticks-blue{list-style:none;margin-bottom:0}ol.counter-blue li,ul.ticks-blue li{position:relative;padding-left:10px}ol.counter-blue li::before,ul.ticks-blue li::before{position:absolute;border:solid 1px #017cee;border-radius:50%}ol.counter-blue{counter-reset:custom-counter;padding-left:-webkit-calc(26px + 2px);padding-left:calc(26px + 2px)}ol.counter-blue li{counter-increment:custom-counter;margin-bottom:25px}ol.counter-blue li::before{content:counter(custom-counter);-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;top:-2px;left:-webkit-calc(-1 * 26px);left:calc(-1 * 26px);width:26px;height:26px;text-align:center;line-height:26px}ul.ticks-blue{padding-left:-webkit-calc(24px + 2px);padding-left:calc(24px + 2px)}ul.ticks-blue li{margin-bottom:22px}ul.ticks-blue li::before{content:"";left:-webkit-calc(-1 * 24px);left:calc(-1 * 24px);width:24px;height:24px;background-position:50%;background-repeat:no-repeat;background-image:url(/images/tick.svg)}.list-items{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin:-20px;-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch}@media(max-width:1280px){.list-items{margin:auto;max-width:580px}}@media(max-width:640px){.list-items{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}}.list-item{width:25%;padding:20px}@media(min-width:1920px){.list-item{width:20%}}@media(max-width:1280px){.list-item{padding:10px;width:50%}}@media(max-width:640px){.list-item{width:100%}}.list-item--wide{width:50%}@media(max-width:1280px){.list-item--wide{width:100%}}.card{border:solid 1px #cbcbcb;border-radius:5px;padding:30px 10px;height:100%}.box-event{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.box-event__blogpost{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;padding:0 20px}.box-event__blogpost--metadata{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;margin-bottom:20px}.box-event__blogpost--header{margin-bottom:4px}.box-event__blogpost--author{font-weight:500}.box-event__blogpost--description{margin-bottom:20px}.box-event__case-study{padding:18px 18px 0;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.box-event__case-study--logo{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;height:60px;width:100%;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.box-event__case-study--logo svg,.box-event__case-study--logo img{max-height:100%;max-width:100%}.box-event__case-study--quote{font-style:italic;margin:30px 0 20px;text-align:center}.box-event__case-study--quote::before{content:"“"}.box-event__case-study--quote::after{content:"”"}.box-event__committer--nick{font-weight:500;margin-top:12px}.box-event__committer--social-media-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.box-event__committer--social-media-icon{margin:0 6px}.box-event__meetup--location{margin-bottom:10px;text-align:center}.box-event__meetup--members{margin-bottom:30px}.box-event__meetup--members span{vertical-align:middle}.box-event__meetup--next-meetup{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;min-height:52px;margin-bottom:20px;text-align:center}.box-event__integration{height:208px;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.box-event__integration--logo{margin:auto 0;-webkit-filter:grayscale(1);filter:grayscale(1);opacity:.6;max-width:100%;max-height:100%}.box-event__integration--name{font-weight:700;text-align:center}.box-event__integration:hover .box-event__integration--logo{-webkit-filter:none;filter:none;opacity:1}.box-event.hoverable-icon svg,.box-event.hoverable-icon img{-webkit-filter:grayscale(1);filter:grayscale(1);opacity:.6;-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s}.box-event.hoverable-icon:hover svg,.box-event.hoverable-icon:hover img{-webkit-filter:none;filter:none;opacity:1}@media(max-width:640px){.box-event__blogpost--metadata{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.box-event__blogpost--date{margin-top:17px}}.avatar{border-radius:50%;width:80px;height:80px}.quote{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;border-bottom:solid 1px #cbcbcb;padding:0 78px 60px}.quote--text{text-align:center;font-weight:400}.quote--text::before{content:"“"}.quote--text::after{content:"”"}.quote--author{text-align:center;font-weight:500;margin-bottom:32px}.quote--logo{max-height:140px;margin:0 auto}@media(max-width:640px){.quote{padding:0 0 40px}}.pager{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;margin-top:60px}.case-study-page{max-width:790px!important;margin:60px auto 0}@media(max-width:640px){.case-study-page{margin-top:40px}}.markdown-content h1,.markdown-content h2,.markdown-content h3,.markdown-content h4,.markdown-content h5{margin-top:40px;margin-bottom:20px}.markdown-content p,.markdown-content span{margin-bottom:30px;margin-top:20px}.markdown-content img{width:100%}.markdown-content table{border-collapse:collapse;width:100%}.markdown-content th{background:#ccc}.markdown-content th,.markdown-content td{border:1px solid #ccc;padding:8px}.markdown-content tr:nth-child(even){background:#efefef}.markdown-content tr:hover{background:#d1d1d1}.markdown-content li{color:#707070}.base-layout{padding:123px 0 40px}.base-layout--button{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;position:-webkit-sticky;position:sticky;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;margin-left:auto;margin-right:40px;bottom:40px;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;z-index:1}@media(max-width:1280px){.base-layout{padding:76px 0 60px}.base-layout--button{display:none}}.page-header{text-align:center;margin-bottom:16px}@media(max-width:1280px){.page-header{font-size:36px!important;line-height:1.22!important}}.page-subtitle{text-align:center;font-weight:400!important;margin-bottom:80px}@media(max-width:1280px){.page-subtitle{font-family:roboto,sans-serif!important;font-size:16px!important;line-height:1.63!important;margin-bottom:30px}}.container{margin-top:44px;max-width:1200px}@media(min-width:1920px){.container{max-width:1510px}}@media(max-width:1280px){.container>*{max-width:630px;margin-left:auto;margin-right:auto}.container .no-width-restriction{max-width:none}}@media(max-width:640px){.container>*{max-width:306px}}.container-fluid{padding-left:20px;padding-right:20px}.show-more-button{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;margin:60px auto 0}@media(max-width:1280px){.show-more-button{margin-top:30px}}@media(max-width:1280px){.desktop-only{display:none}}@media(min-width:calc(1280px + 1px)){.no-desktop{display:none}}@media(min-width:calc(640px + 1px)){.mobile-only{display:none}}.features-list{margin:76px auto 100px;max-width:720px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}@media(min-width:1920px){.features-list{max-width:unset;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;margin-top:0}}@media(max-width:640px){.features-list{margin-top:0}}.feature-item{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin:44px auto 0}.feature-item--icon-box{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;max-width:150px;width:100%;height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;margin-top:18px}.feature-item--text-box{margin-left:60px}@media(min-width:1920px),(max-width:1280px){.feature-item{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.feature-item--icon-box{margin-top:0;margin-bottom:20px;max-width:unset}.feature-item--text-box{margin-left:0;text-align:center}}@media(min-width:1920px){.feature-item{margin-top:60px;max-width:392px;margin-left:40px;margin-right:40px}}@media(max-width:1280px){.feature-item{margin-top:40px;max-width:260px}.feature-item svg{height:60px;width:auto}.feature-item--header{font-family:roboto,sans-serif!important;font-size:24px!important;line-height:1.5!important}.feature-item--text{font-size:14px!important;line-height:1.57!important}}.text-with-icon-list{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;max-width:940px;margin:0 auto 100px;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.text-with-icon-item{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-width:410px;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;margin-top:54px}.text-with-icon-item svg{height:100px}.text-with-icon-item--header{text-align:center;margin-top:23px}.text-with-icon-item--text{text-align:center}@media(min-width:1920px){.text-with-icon-list{max-width:unset}.text-with-icon-item{max-width:305px}}@media(max-width:1280px){.text-with-icon-item{margin-top:30px;max-width:276px}.text-with-icon-item svg{width:70px;height:70px}.text-with-icon-item--header{font-family:roboto,sans-serif;font-size:24px;line-height:1.5;margin-top:16px}.text-with-icon-item--text{font-size:14px;line-height:1.57}}@media(max-width:640px){.text-with-icon-list{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}}.video-section{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;border:solid 1px #cbcbcb;padding:40px}@media(max-width:1280px){.video-section{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-width:560px;margin:0 auto;padding:20px}}.video-wrapper{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.video-wrapper .video-container{display:none}.video-wrapper .video-container:last-child{display:block}.video-wrapper .anchor{position:fixed}.video-wrapper .anchor:target+.video-container{display:block}.video-wrapper .anchor:target+.video-container~.video-container{display:none}.video-list-wrapper{overflow-y:auto;max-height:403px;max-width:370px;width:100%;margin-left:40px}@media(max-width:1280px){.video-list-wrapper{max-width:unset;margin-left:0}}.video-list-wrapper::-webkit-scrollbar{-webkit-appearance:none}.video-list-wrapper::-webkit-scrollbar-thumb{border-radius:8px;border:2px solid #fff;background-color:rgba(0,0,0,.5)}.video-list-wrapper::-webkit-scrollbar:vertical{width:9px}.video-list{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end}.video-list__item{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;border-bottom:solid 1px #cbcbcb;padding:16px 0}.video-list__item .video-list__item--title{margin-left:9px;vertical-align:middle}.video-list__item--icon-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.video-list__item:hover .video-list__item--title,.video-list__item.active .video-list__item--title{font-weight:500}.video-list__item:hover svg path,.video-list__item.active svg path{fill:#707070;stroke:none}.tag{display:block;background-color:rgba(1,124,238,.25);padding:1px 15px;border-radius:5px;-webkit-transition:.2s;-o-transition:.2s;transition:.2s;margin:7px}.tag.active,.tag:hover{background-color:#017cee;color:#fff}.tags-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;margin:-7px}@media(max-width:640px){.tags-container{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;margin-bottom:7px}}.all-tags-container{margin:30px 0}.blog__list-items-wrapper{max-width:1200px;margin:30px auto 0}@media(max-width:1280px){.blog__list-items-wrapper{max-width:580px}}.new-entry{margin-bottom:20px}.new-entry--link{font-weight:500}@media(max-width:1280px){.new-entry{margin-bottom:10px;padding-left:10px}}.blogpost-content{max-width:790px;margin:0 auto}.blogpost-content--header-wrapper{border-bottom:solid 1px #cbcbcb}.blogpost-content__metadata--container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;margin-bottom:30px}.blogpost-content__metadata--title{margin-bottom:20px}.blogpost-content__metadata--author{font-weight:500;margin-bottom:30px;margin-right:17px}.blogpost-content__metadata--social-media-icon{margin-right:7px}.blogpost-content__metadata--description{font-weight:400;margin-bottom:30px}.blogpost-content__metadata--date{margin-top:17px}@media(max-width:640px){.blogpost-content__metadata--container{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;margin-bottom:19px}.blogpost-content__metadata--title{font-family:roboto,sans-serif!important;font-size:24px!important;line-height:1.5!important;max-width:272px;margin-bottom:13px}.blogpost-content__metadata--author{margin-bottom:20px}.blogpost-content__metadata--description{font-family:roboto,sans-serif!important;font-weight:400!important;font-size:16px!important;line-height:1.63!important;margin-bottom:20px}}.blog-pager{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;max-width:1200px;margin:60px auto 0}.blog-pager .pager{margin-top:40px;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.home-page-layout.base-layout{padding-top:70px}@media(max-width:640px){.home-page-layout.base-layout{padding-top:16px}}.principles-header{margin-top:20px;margin-bottom:4px}.integrations-header{margin-bottom:60px}@media(max-width:640px){.integrations-header{margin-bottom:30px}}#integrations .list-items{margin-top:40px}@media(max-width:640px){#integrations .list-items{margin-top:20px}}.video-section-container{margin:80px auto;max-width:1200px}@media(max-width:640px){.video-section-container{margin:60px 0}}.host-header{margin-bottom:6px}.meetups{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.meetups>.list-items{margin-top:40px;margin-bottom:40px;width:100%}@media(max-width:1280px){.meetups>.list-items{margin-top:30px;margin-bottom:30px}}@media(max-width:640px){.meetups>.list-items{margin-bottom:10px}}.meetups-page.page-subtitle{margin-bottom:0}.list-link{text-decoration:underline}.community--header-container{max-width:936px;margin:0 auto}.community--header-join{text-align:center}.community--accordion-container{margin:60px 18px}.community--committers-header{text-align:center;margin-top:70px;margin-bottom:40px}.community--committers-header.large-margin{margin-top:100px;margin-bottom:40px}@media(min-width:1920px){.community .list-items{max-width:1220px;margin-right:auto;margin-left:auto}.community .list-item{width:25%}}@media(max-width:1280px){.community--header-container{max-width:580px}.community--header-join{font-family:roboto,sans-serif!important;font-size:24px!important;line-height:1.5!important}.community--accordion-container{margin:40px 0}.community--committers-header{font-size:36px!important;line-height:1.22!important;margin-top:60px}.community--committers-header.large-margin{margin-top:60px;margin-bottom:40px}.community--button-container{margin-top:20px}}.install .page-subtitle{margin-bottom:45px}.install--headers-wrapper{max-width:936px;margin:0 auto}.install--description{text-align:center;margin:45px 0 60px}.install--description a{color:#017cee;text-decoration:underline}.install__accordions--wrapper{max-width:900px;margin:60px auto}.install__accordions-content--header{font-weight:500}.install__accordions-content--list-wrapper{margin-bottom:40px}.install__accordions-content--methods-wrapper{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-bottom:20px}.install__accordions-content--method-box{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:270px;height:160px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;border:solid 1px #cbcbcb;border-radius:5px;margin-right:40px}@media(max-width:1280px){.install .page-subtitle{margin-bottom:30px}.install--headers-wrapper{max-width:580px}.install--description{margin-top:30px;margin-bottom:30px}.install__accordions--wrapper{max-width:580px;margin-top:40px;margin-bottom:0}}@media(max-width:640px){.install__accordions-content--methods-wrapper{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;margin-bottom:0;margin-right:-36px}.install__accordions-content--method-box{margin-right:0;margin-bottom:20px}}footer{min-height:unset}footer .footer-section{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}footer .footer-section__media-section{padding:60px 60px 30px;background-color:#51504f}footer .footer-section__media-section--link{margin-right:30px}footer .footer-section__media-section--button-with-text{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}footer .footer-section__media-section--text{margin-right:20px}footer .footer-section__policies-section{padding:30px 60px;background-color:#636365;font-size:12px;-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}footer .footer-section__policies-section span{font-size:12px}footer .footer-section__policies-section--policies{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}footer .footer-section__policies-section--policy-item::before{content:"\00a0\00a0"}footer .footer-section__policies-section--policy-item::after{content:"\00a0\00a0|";color:#fff}footer .footer-section__policies-section--policy-item:last-of-type::after{content:"\00a0\00a0|\00a0\00a0"}footer .footer-section__policies-section--disclaimer{display:block;max-width:600px;color:#cbcbcb!important;margin-top:16px}@media(min-width:1920px){footer .footer-section__policies-section--disclaimer{max-width:800px}}footer .dropdown-toggle::after{color:#fff;vertical-align:middle}@media(max-width:1280px){footer .footer-section{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start}footer .footer-section span{font-size:14px!important;line-height:1.57!important}footer .footer-section__media-section{padding:30px 40px}footer .footer-section__media-section svg{height:31px;width:auto}footer .footer-section__media-section--link{margin-right:20px}footer .footer-section__media-section--button-with-text{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;margin-bottom:47px}footer .footer-section__media-section--text{margin-right:0;margin-bottom:16px}footer .footer-section__policies-section{padding:30px 40px}footer .footer-section__policies-section--policies{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}footer .footer-section__policies-section--policy-item::before,footer .footer-section__policies-section--policy-item::after,footer .footer-section__policies-section--policy-item:last-of-type::before,footer .footer-section__policies-section--policy-item:last-of-type::after{content:""}footer .footer-section__policies-section--language-toggle{margin:17px 0 35px}}.navbar{position:fixed;top:0;width:100%;background-color:#fff;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start;border-bottom:solid 1px #cbcbcb;z-index:32;padding:30px 60px}.navbar__menu-container{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1}.navbar__menu-content{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding-top:16px;padding-left:88px}.navbar__links-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.navbar__text-link{margin-right:30px;position:relative;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.navbar__text-link::before,.navbar__text-link::after{content:"";position:absolute;top:100%;width:0;right:0;height:2px;background-color:#017cee;-webkit-transition:.2s ease-out;-o-transition:.2s ease-out;transition:.2s ease-out}.navbar__text-link:hover,.navbar__text-link.active{color:#51504f}.navbar__text-link:hover::before,.navbar__text-link:hover::after,.navbar__text-link.active::before,.navbar__text-link.active::after{width:100%;left:0}.navbar--box-shadow{-webkit-box-shadow:0 2px 6px 0 rgba(0,0,0,.12);box-shadow:0 2px 6px 0 rgba(0,0,0,.12)}@media(max-width:1280px){.navbar{padding:20px}.navbar__icon-container svg{width:93px;height:auto}.navbar__menu-content{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;padding-left:0;padding-top:0}.navbar__drawer-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end}.navbar__toggle-button{border:none;background:0 0;padding:0;position:relative;width:26px;height:20px}.navbar__toggle-button--icon{position:absolute;top:0;bottom:0;left:0;right:0;visibility:hidden;opacity:0;-webkit-transition:.2s ease-out;-o-transition:.2s ease-out;transition:.2s ease-out}.navbar__toggle-button--icon.visible{visibility:visible;opacity:1}.navbar__drawer{position:fixed;top:77px;left:0;width:100%;height:-webkit-calc(100% - 77px);height:calc(100% - 77px);background-color:#fff;-webkit-transform:translateX(100%);-ms-transform:translateX(100%);-o-transform:translateX(100%);transform:translateX(100%);-webkit-transition:.2s ease-out;-o-transition:.2s ease-out;transition:.2s ease-out;padding:40px 40px 30px}.navbar__drawer--open{-webkit-transform:translateX(0);-ms-transform:translateX(0);-o-transform:translateX(0);transform:translateX(0)}.navbar__links-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.navbar__text-link{margin-right:0;margin-bottom:10px}.navbar__text-link:last-child{margin-bottom:20px}}#header{position:relative;margin:123px -20px 0;min-height:-webkit-calc(100vh - 123px);min-height:calc(100vh - 123px)}#header-canvas{padding:0;margin:0;position:absolute;width:100%;height:100%;top:0;left:0;right:0;bottom:0}#header-canvas .text-area{max-width:706px;width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);-o-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}#header-canvas .text-area--header{text-align:center;margin-bottom:20px}#header-canvas .text-area--subheader{font-weight:400!important;text-align:center;margin-bottom:20px}#header-canvas canvas{position:absolute;top:0;left:0;width:100%;height:100%;z-index:-1}@media(min-width:1920px){#header-canvas .text-area--header{font-size:90px}}@media(max-width:1280px){#header{margin:77px -20px 0;min-height:-webkit-calc(100vh - 77px);min-height:calc(100vh - 77px)}#header-canvas .text-area{max-width:450px}#header-canvas .text-area--header{margin-bottom:14px}#header-canvas .text-area--subheader{margin-bottom:26px}}@media(max-width:640px){#header-canvas .text-area{max-width:290px}#header-canvas .text-area--header{font-size:48px!important;line-height:1.25!important}#header-canvas .text-area--subheader{font-size:16px!important;line-height:1.63!important}}.roadmap{margin-top:40px}.roadmap main{padding-left:40px}.roadmap .breadcrumb{padding-bottom:0;margin-bottom:30px}.roadmap .breadcrumb-item+.breadcrumb-item{padding-left:4px}.roadmap .breadcrumb-item+.breadcrumb-item::before{color:#707070;padding-right:0}.roadmap .td-sidebar{position:-webkit-sticky;position:sticky;top:163px;height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;max-height:-webkit-calc(100vh - 163px);max-height:calc(100vh - 163px);max-width:270px;min-width:270px;width:100%;overflow-y:auto;padding-top:12px;padding-left:15px;padding-bottom:30px;margin-left:40px;background-color:#f9f9f9;border:none}.roadmap .td-sidebar::-webkit-scrollbar{-webkit-appearance:none}.roadmap .td-sidebar::-webkit-scrollbar-thumb{border-radius:8px;border:2px solid #fff;background-color:rgba(0,0,0,.5)}.roadmap .td-sidebar::-webkit-scrollbar:vertical{width:9px}.roadmap .td-sidebar__inner{position:static;height:unset}.roadmap .td-sidebar li>a{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.roadmap .td-sidebar li>a.active{color:#017cee}.roadmap .td-sidebar .searchb-box{margin-bottom:26px}.roadmap .td-sidebar .searchb-box .search-form{width:100%}.roadmap .td-sidebar .toctree li{list-style:none;font-family:roboto,sans-serif;font-size:16px;font-weight:400;font-stretch:normal;font-style:normal;line-height:1.63;letter-spacing:normal;color:#707070}.roadmap .td-sidebar .toctree ul{padding-left:15px;display:none}.roadmap .td-sidebar .toctree>ul,.roadmap .td-sidebar .toctree li.current>ul{display:block}.roadmap .td-sidebar .toctree .caption{font-family:roboto,sans-serif;font-size:18px;font-weight:700;font-stretch:normal;font-style:normal;line-height:1.33;letter-spacing:normal;color:#51504f;padding-bottom:13px;text-transform:uppercase;margin-bottom:0}.roadmap .td-sidebar .toctree .current{color:#017cee;font-weight:500}.roadmap .td-sidebar .toctree .current>a:not([href="#"]){color:#017cee}.roadmap .td-sidebar .toctree a .toctree-expand{display:inline-block;position:relative;height:1em}.roadmap .td-sidebar .toctree a .toctree-expand::before{position:absolute;top:6px;left:-12px;content:'►';font-size:7px}.roadmap .td-sidebar .toctree .current>a>.toctree-expand:before{content:'▼'}.roadmap .td-sidebar-nav__section{padding-right:0}.roadmap .td-sidebar-nav>.td-sidebar-nav__section .td-sidebar-nav__section{list-style:none;position:relative;margin-left:10px}.roadmap .td-sidebar-nav>.td-sidebar-nav__section .td-sidebar-nav__section::before{content:'►';position:absolute;top:6px;left:-12px;font-size:8px;color:#51504f}.roadmap .td-sidebar-nav>.td-sidebar-nav__section .td-sidebar-nav__section>ul{display:none}.roadmap .td-sidebar-nav>.td-sidebar-nav__section .td-sidebar-nav__section.current-section::before{content:'▼'}.roadmap .td-sidebar-nav>.td-sidebar-nav__section .td-sidebar-nav__section.current-section>ul{display:block}.roadmap .wy-nav-side-toc{position:-webkit-sticky;position:sticky;top:163px;overflow-x:hidden;overflow-y:auto;width:280px;height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;max-height:-webkit-calc(100vh - 163px);max-height:calc(100vh - 163px);font-size:14px;line-height:1.43}.roadmap .wy-nav-side-toc::-webkit-scrollbar{-webkit-appearance:none}.roadmap .wy-nav-side-toc::-webkit-scrollbar-thumb{border-radius:8px;border:2px solid #fff;background-color:rgba(0,0,0,.5)}.roadmap .wy-nav-side-toc::-webkit-scrollbar:vertical{width:9px}.roadmap .wy-nav-side-toc ul,.roadmap .wy-nav-side-toc ol{padding:0;list-style:none none}.roadmap .wy-nav-side-toc li{list-style:none}.roadmap .wy-nav-side-toc .wy-menu-vertical>ul,.roadmap .wy-nav-side-toc .wy-menu-vertical li.current>ul{padding-left:1px}.roadmap .wy-nav-side-toc .wy-menu-vertical a{display:inline-block;padding:.4045em 0;color:#707070}.roadmap .wy-nav-side-toc .wy-menu-vertical li a{border-left:solid 2px #cbcbcb;padding-left:-webkit-calc(1.25em + 1px);padding-left:calc(1.25em + 1px)}.roadmap .wy-nav-side-toc .wy-menu-vertical li.current{margin-left:-1px}.roadmap .wy-nav-side-toc .wy-menu-vertical li.current>a{border-left:solid 4px #017cee;color:#017cee}.roadmap .wy-nav-side-toc .wy-menu-vertical li li>a{padding-left:2.427em}.roadmap .wy-nav-side-toc .wy-menu-vertical li li li>a{padding-left:4.045em}.roadmap .wy-nav-side-toc .wy-menu-vertical li li li li>a{padding-left:5.663em}@media(max-width:1280px){.roadmap main{padding-left:0}.roadmap .td-sidebar{position:static;background-color:transparent;padding:0;margin:0;max-width:unset;height:530px}}.search-form{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:344px;padding:8px 20px;border:solid 1px #cbcbcb;border-radius:5px;margin:60px auto 0}.search-form__input{font-family:roboto,sans-serif;font-size:16px;color:#707070;line-height:1.63;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;padding-right:10px;border:none;background:0 0;outline:none;float:left}.search-form__button{border:none;background-color:transparent;padding:0}@media(max-width:1280px){.search-form{width:270px;padding:3px 20px;margin-top:30px}}.rating-container{margin-top:40px}.rating{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.rate-star{cursor:pointer;margin-right:13px}.rate-star svg path{fill:none;stroke:#51504f}.rate-star:hover svg path,.rate-star:hover~.rate-star svg path{fill:#017cee;stroke:none}.rst-content{color:#707070}.rst-content h1{margin-top:0;margin-bottom:30px;font-weight:500;font-family:rubik,sans-serif;color:#51504f;font-size:225%}.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6,.rst-content p{font-family:roboto,sans-serif;color:#707070}.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-top:40px;margin-bottom:20px;font-weight:500}.rst-content p{line-height:1.63;margin:0 0 30px;font-size:16px;overflow-wrap:break-word}.rst-content h2{font-size:150%}.rst-content h3{font-size:125%}.rst-content h4{font-size:115%}.rst-content h5{font-size:110%}.rst-content h6{font-size:100%}.rst-content code{max-width:100%;color:#51504f;padding:0 5px;font-family:roboto mono,monospace;overflow-x:auto}.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .admonition-todo,.rst-content .admonition{padding:9px 10px;line-height:24px;margin-bottom:24px;background:#e7f2fa}@media(max-width:768px){.rst-content .admonition p:not(.admonition-title){font-size:12px;line-height:1.83}}.rst-content .admonition-title:before{content:"!";background-color:#fff;border-radius:50%;padding:0 4px;margin-right:5px}.rst-content .admonition-title{color:#fff;font-weight:500;font-size:10px;line-height:2.1;display:block;background:#68d1ff;margin:-10px;padding:0 12px;margin-bottom:9px}.rst-content .danger,.rst-content .error{background:#fdece9}.rst-content .danger::before,.rst-content .error::before{color:#fdece9}.rst-content .danger .admonition-title,.rst-content .error .admonition-title{background:#ee8170}.rst-content .danger .admonition-title::before,.rst-content .error .admonition-title::before{color:#ee8170}.rst-content .attention,.rst-content .caution{background:#fff8f6}.rst-content .warning{background:#f8f8f8}.rst-content .attention .admonition-title,.rst-content .caution .admonition-title{background:#ffa996}.rst-content .attention .admonition-title::before,.rst-content .caution .admonition-title::before{color:#ffa996}.rst-content .warning .admonition-title{background:#a6a6a6}.rst-content .warning .admonition-title::before{color:#a6a6a6}.rst-content .note,.rst-content .seealso{background:#f3fbff}.rst-content .note .admonition-title,.rst-content .seealso .admonition-title{background:#68d2fe}.rst-content .note .admonition-title::before,.rst-content .seealso .admonition-title::before{color:#68d2fe}.rst-content .hint{background:#f2fef6}.rst-content .important{background:#e6f9fc}.rst-content .tip{background:#e5f7ec}.rst-content .hint .admonition-title{background:#63e598}.rst-content .hint .admonition-title::before{color:#63e598}.rst-content .important .admonition-title{background:#5bdae3}.rst-content .important .admonition-title::before{color:#5bdae3}.rst-content .tip .admonition-title{background:#5bcb88}.rst-content .tip .admonition-title::before{color:#5bcb88}.rst-content .note p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.rst-content .seealso p:last-child,.rst-content .admonition p:last-child{margin-bottom:0}.rst-content img{max-width:100%;height:auto}.rst-content div.figure{margin-bottom:24px}.rst-content div.figure p.caption{font-style:italic}.rst-content div.figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center{text-align:center}.rst-content .section>img,.rst-content .section>a>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre{background-color:#f2f8fe}.rst-content pre.literal-block,.rst-content .linenodiv pre{font-family:roboto mono,monospace;font-size:12px;line-height:1.4}@media print{.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol p,.rst-content .section ul p{margin-bottom:12px}.rst-content .section ol li p:last-child,.rst-content .section ul li p:last-child{margin-bottom:0}.rst-content .section ol p:last-child,.rst-content .section ul p:last-child{margin-bottom:24px}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:inherit}.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content .toctree-wrapper p.caption .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink,.rst-content .code-block-caption .headerlink{visibility:hidden;font-size:0}.rst-content h1 .headerlink:after,.rst-content h2 .headerlink:after,.rst-content .toctree-wrapper p.caption .headerlink:after,.rst-content h3 .headerlink:after,.rst-content h4 .headerlink:after,.rst-content h5 .headerlink:after,.rst-content h6 .headerlink:after,.rst-content dl dt .headerlink:after,.rst-content p.caption .headerlink:after,.rst-content table>caption .headerlink:after,.rst-content .code-block-caption .headerlink:after{content:url(/images/anchor.svg);vertical-align:bottom;padding-left:8px}.rst-content h1:hover .headerlink:after,.rst-content h2:hover .headerlink:after,.rst-content .toctree-wrapper p.caption:hover .headerlink:after,.rst-content h3:hover .headerlink:after,.rst-content h4:hover .headerlink:after,.rst-content h5:hover .headerlink:after,.rst-content h6:hover .headerlink:after,.rst-content dl dt:hover .headerlink:after,.rst-content p.caption:hover .headerlink:after,.rst-content table>caption:hover .headerlink:after,.rst-content .code-block-caption:hover .headerlink:after{visibility:visible}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .footnote-reference,.rst-content .citation-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content table.docutils,.rst-content table.field-list{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption{padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list th{margin:0;overflow:visible}.rst-content table.docutils td{padding:10px 31px}.rst-content table.docutils th,.rst-content table.field-list th{padding:11px 31px}.rst-content table.docutils td:first-child,.rst-content table.field-list td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead{text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th{border-bottom:solid 1px rgba(81,80,79,.3);border-left:solid 1px rgba(81,80,79,.3)}.rst-content table.docutils thead th p,.rst-content table.field-list thead th p{font-weight:700;font-size:18px;color:#51504f;line-height:1.33;margin-bottom:0}.rst-content table.docutils td,.rst-content table.field-list td{background-color:transparent;vertical-align:middle}.rst-content td p:last-child,.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child{margin-bottom:0}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td{background-color:rgba(112,112,112,.05)}.rst-content table.docutils{border:1px solid rgba(81,80,79,.3)}.rst-content table.docutils td{border-bottom:1px solid rgba(81,80,79,.3);border-left:1px solid rgba(81,80,79,.3)}.rst-content table.docutils tbody>tr:last-child td{border-bottom-width:0}.rst-content .wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.rst-content .wy-table-responsive table{margin-bottom:0!important}.rst-content .wy-table-responsive table td,.rst-content .wy-table-responsive table th{white-space:nowrap}.rst-content code big,.rst-content tt em,.rst-content code em{font-size:100%!important;line-height:normal}.rst-content code.literal{color:#e74c3c}.rst-content code.xref,.rst-content a code{font-weight:700;color:#707070}.rst-content pre,.rst-content kbd{font-family:roboto mono,monospace}.rst-content kbd{background-color:inherit;color:inherit;-webkit-box-shadow:none;box-shadow:none;border:none;font-size:100%}.rst-content a code{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px;word-break:break-word}.rst-content dl p,.rst-content dl table,.rst-content dl ul,.rst-content dl ol{margin-bottom:12px!important}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl:not(.docutils){margin-bottom:24px}.rst-content dl:not(.docutils) dt{font-family:roboto mono,monospace;display:table;margin:6px 0;font-size:100%;line-height:1.63;background:#f3fbff;color:#51504f;border-top:solid 4px #68d1ff;padding:8px 10px;position:relative}@media(max-width:768px){.rst-content dl:not(.docutils) dt{font-size:10px}}.rst-content dl:not(.docutils) dt:before{color:#68d1ff}.rst-content dl:not(.docutils) dt .headerlink{color:#707070;font-size:100%!important}.rst-content dl:not(.docutils) dt .fn-backref{color:#0cb6ff}.rst-content dl:not(.docutils) dl dt{margin-bottom:6px;border:none;border-left:solid 8px #a6a6a6;background:#f8f8f8;color:#707070}.rst-content dl:not(.docutils) dl dt .headerlink{color:#707070;font-size:100%!important}.rst-content dl:not(.docutils) dt:first-child{margin-top:0}.rst-content dl:not(.docutils) code{font-weight:700}.rst-content dl:not(.docutils) code.descname,.rst-content dl:not(.docutils) code.descclassname{background-color:transparent;border:none;padding:0;font-size:100%!important}.rst-content dl:not(.docutils) code.descname{font-weight:700}.rst-content dl:not(.docutils) .optional{display:inline-block;padding:0 4px;color:#51504f;font-weight:700}.rst-content dl:not(.docutils) .property{display:inline-block;padding-right:8px}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content .versionmodified{font-style:italic}.rst-content .example-header{position:relative;background:#017cee;padding:8px 16px;margin-bottom:0}.rst-content .example-block-wrapper pre{margin:0;width:unset;border-top-left-radius:0;border-top-right-radius:0}.rst-content .example-header--with-button{padding-right:166px}@media(max-width:768px){.rst-content .example-header--with-button{padding-right:100px}}.rst-content .example-header:after{content:'';display:table;clear:both}.rst-content .example-title{display:block;padding:4px;margin-right:16px;color:#fff;overflow-x:auto}@media(max-width:768px){.rst-content .example-title{overflow-wrap:initial;font-size:12px}}.rst-content .example-header-button{top:8px;right:16px;position:absolute}.rst-content .example-header+.highlight-python{margin-top:0!important}.rst-content .viewcode-button{display:inline-block;padding:8px 16px;border:0;margin:0;color:#fff;font-weight:700;line-height:1;text-decoration:underline;text-overflow:ellipsis;overflow:hidden;text-transform:lowercase;vertical-align:middle;white-space:nowrap}@media(max-width:768px){.rst-content .viewcode-button{font-size:12px;padding:7px 0}}.rst-content .viewcode-button:visited{color:#404040}.rst-content .viewcode-button:hover,.rst-content .viewcode-button:focus{color:#404040}@media(min-width:1024px){.rst-content .section::before{display:block;content:" ";margin-top:-83px;height:83px;visibility:hidden}}.content-drawer-wrapper{display:none}@media(max-width:1280px){.content-drawer-wrapper{display:block;margin-bottom:30px}}.content-drawer-wrapper .navbar{-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;left:0}.content-drawer-wrapper .navbar--hidden{display:none}.content-drawer-container{position:fixed;top:77px;left:0;width:100%;height:100%;background-color:#fff;-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);-o-transform:translateX(-100%);transform:translateX(-100%);-webkit-transition:.2s ease-out;-o-transition:.2s ease-out;transition:.2s ease-out;z-index:100}.content-drawer-container--open{-webkit-transform:translateX(0);-ms-transform:translateX(0);-o-transform:translateX(0);transform:translateX(0)}.content-drawer{padding:20px 40px}.content-drawer__toggle-button{border:none;background:0 0;padding:0;position:relative;width:26px;height:20px}.content-drawer__toggle-button--icon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;visibility:hidden;opacity:0;-webkit-transition:.2s ease-out;-o-transition:.2s ease-out;transition:.2s ease-out}.content-drawer__toggle-button--icon svg{margin-right:10px}.content-drawer__toggle-button--icon.visible{visibility:visible;opacity:1}.dropdown-menu{font-family:roboto,sans-serif}.dropdown-toggle::after{color:#51504f}.sidebar__version-selector{margin-bottom:22px}.chroma,.highlight{background-color:#fff}.chroma .lntd,.highlight .lntd{vertical-align:top;padding:0;margin:0;border:0}.chroma .lntable,.highlight .lntable{border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block}.chroma .hl,.highlight .hl{display:block;width:100%;background-color:#ffc}.chroma .lnt,.chroma .ln,.highlight .lnt,.highlight .ln{margin-right:.4em;padding:0 .4em;color:#7f7f7f}.chroma .k,.chroma .kc,.chroma .kd,.chroma .kn,.chroma .kp,.chroma .kr,.highlight .k,.highlight .kc,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr{color:#00f}.chroma .kt,.chroma .nc,.highlight .kt,.highlight .nc{color:#2b91af}.chroma .s,.chroma .sa,.chroma .sb,.chroma .sc,.chroma .dl,.chroma .sd,.chroma .s2,.chroma .se,.chroma .sh,.chroma .si,.chroma .sx,.chroma .sr,.chroma .s1,.chroma .ss,.highlight .s,.highlight .sa,.highlight .sb,.highlight .sc,.highlight .dl,.highlight .sd,.highlight .s2,.highlight .se,.highlight .sh,.highlight .si,.highlight .sx,.highlight .sr,.highlight .s1,.highlight .ss{color:#a31515}.chroma .ow,.highlight .ow{color:#00f}.chroma .c,.chroma .ch,.chroma .cm,.chroma .c1,.chroma .cs,.highlight .c,.highlight .ch,.highlight .cm,.highlight .c1,.highlight .cs{color:green}.chroma .cp,.chroma .cpf,.highlight .cp,.highlight .cpf{color:#00f}.chroma .ge,.highlight .ge{font-style:italic}.chroma .gh,.chroma .gp,.chroma .gs,.chroma .gu,.highlight .gh,.highlight .gp,.highlight .gs,.highlight .gu{font-weight:700}pre{margin:40px 0;padding:16px 20px;border:solid 1px #cbcbcb;border-radius:5px;width:100%}.share-section--icons-wrapper{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.share-section--icon{margin-right:12px;cursor:pointer}.four-oh-four{height:-webkit-calc(100vh - 123px);height:calc(100vh - 123px);position:relative}.four-oh-four__text-container{position:relative;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);-o-transform:translate(-50%,-50%);transform:translate(-50%,-50%);text-align:center} \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_static/_gen/css/main.min.css b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/_gen/css/main.min.css new file mode 100644 index 00000000000..603f3cb39ff --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/_gen/css/main.min.css @@ -0,0 +1,7 @@ +@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,700,700i";@fa-font-path:"../webfonts";/*!* Bootstrap v4.1.3 (https://getbootstrap.com/) +* Copyright 2011-2018 The Bootstrap Authors +* Copyright 2011-2018 Twitter, Inc. +* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)*/:root{--blue: #72A1E5;--indigo: #6610f2;--purple: #6f42c1;--pink: #e83e8c;--red: #dc3545;--orange: #BA5A31;--yellow: #ffc107;--green: #28a745;--teal: #20c997;--cyan: #17a2b8;--white: #fff;--gray: #888;--gray-dark: #333;--primary: #30638E;--secondary: #FFA630;--success: #3772FF;--info: #C0E0DE;--warning: #ED6A5A;--danger: #ED6A5A;--light: #D3F3EE;--dark: #403F4C;--breakpoint-xs: 0;--breakpoint-sm: 576px;--breakpoint-md: 768px;--breakpoint-lg: 992px;--breakpoint-xl: 1200px;--font-family-sans-serif: "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}*,*::before,*::after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:rgba(0,0,0,0)}@-ms-viewport{width:device-width;}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:open sans,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;font-size:1rem;font-weight:400;line-height:1.5;color:#222;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[title],abbr[data-original-title]{text-decoration:underline;-webkit-text-decoration:underline dotted;-moz-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#3176d9;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#1e53a0;text-decoration:none}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):hover,a:not([href]):not([tabindex]):focus{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}pre,code,kbd,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,liberation mono,courier new,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#888;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}button,html [type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{padding:0;border-style:none}input[type=radio],input[type=checkbox]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{margin-bottom:.5rem;font-family:inherit;font-weight:500;line-height:1.2;color:inherit}h1,.h1{font-size:2.25rem}h2,.h2{font-size:2rem}h3,.h3{font-size:1.5rem}h4,.h4{font-size:1.35rem}h5,.h5{font-size:1.15rem}h6,.h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:3rem;font-weight:700;line-height:1.2}.display-2{font-size:2.5rem;font-weight:700;line-height:1.2}.display-3{font-size:2rem;font-weight:700;line-height:1.2}.display-4{font-size:1.75rem;font-weight:700;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}small,.small{font-size:80%;font-weight:400}mark,.mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#888}.blockquote-footer::before{content:"\2014 \00A0"}.img-fluid,.td-content img{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075);max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#888}code{font-size:87.5%;color:#c97300;word-break:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#222;border-radius:.2rem;-webkit-box-shadow:inset 0 -.1rem 0 rgba(0,0,0,.25);box-shadow:inset 0 -.1rem 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;font-size:87.5%;color:#222}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media(min-width:576px){.container{max-width:540px}}@media(min-width:768px){.container{max-width:720px}}@media(min-width:992px){.container{max-width:960px}}@media(min-width:1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-11,.col-12,.col,.col-auto,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm,.col-sm-auto,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-md,.col-md-auto,.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg,.col-lg-auto,.col-xl-1,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl,.col-xl-auto{position:relative;width:100%;min-height:1px;padding-right:15px;padding-left:15px}.col{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333333%;-ms-flex:0 0 8.33333333%;flex:0 0 8.33333333%;max-width:8.33333333%}.col-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66666667%;-ms-flex:0 0 16.66666667%;flex:0 0 16.66666667%;max-width:16.66666667%}.col-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333333%;-ms-flex:0 0 33.33333333%;flex:0 0 33.33333333%;max-width:33.33333333%}.col-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66666667%;-ms-flex:0 0 41.66666667%;flex:0 0 41.66666667%;max-width:41.66666667%}.col-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333333%;-ms-flex:0 0 58.33333333%;flex:0 0 58.33333333%;max-width:58.33333333%}.col-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66666667%;-ms-flex:0 0 66.66666667%;flex:0 0 66.66666667%;max-width:66.66666667%}.col-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333333%;-ms-flex:0 0 83.33333333%;flex:0 0 83.33333333%;max-width:83.33333333%}.col-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66666667%;-ms-flex:0 0 91.66666667%;flex:0 0 91.66666667%;max-width:91.66666667%}.col-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.order-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.order-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.order-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.order-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.order-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.order-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.order-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.order-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.order-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.order-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.order-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.order-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.order-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.order-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}@media(min-width:576px){.col-sm{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-sm-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333333%;-ms-flex:0 0 8.33333333%;flex:0 0 8.33333333%;max-width:8.33333333%}.col-sm-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66666667%;-ms-flex:0 0 16.66666667%;flex:0 0 16.66666667%;max-width:16.66666667%}.col-sm-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333333%;-ms-flex:0 0 33.33333333%;flex:0 0 33.33333333%;max-width:33.33333333%}.col-sm-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66666667%;-ms-flex:0 0 41.66666667%;flex:0 0 41.66666667%;max-width:41.66666667%}.col-sm-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333333%;-ms-flex:0 0 58.33333333%;flex:0 0 58.33333333%;max-width:58.33333333%}.col-sm-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66666667%;-ms-flex:0 0 66.66666667%;flex:0 0 66.66666667%;max-width:66.66666667%}.col-sm-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333333%;-ms-flex:0 0 83.33333333%;flex:0 0 83.33333333%;max-width:83.33333333%}.col-sm-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66666667%;-ms-flex:0 0 91.66666667%;flex:0 0 91.66666667%;max-width:91.66666667%}.col-sm-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.order-sm-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.order-sm-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.order-sm-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.order-sm-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.order-sm-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.order-sm-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.order-sm-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.order-sm-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.order-sm-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.order-sm-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.order-sm-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.order-sm-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.order-sm-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.order-sm-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}}@media(min-width:768px){.col-md{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-md-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333333%;-ms-flex:0 0 8.33333333%;flex:0 0 8.33333333%;max-width:8.33333333%}.col-md-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66666667%;-ms-flex:0 0 16.66666667%;flex:0 0 16.66666667%;max-width:16.66666667%}.col-md-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333333%;-ms-flex:0 0 33.33333333%;flex:0 0 33.33333333%;max-width:33.33333333%}.col-md-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66666667%;-ms-flex:0 0 41.66666667%;flex:0 0 41.66666667%;max-width:41.66666667%}.col-md-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333333%;-ms-flex:0 0 58.33333333%;flex:0 0 58.33333333%;max-width:58.33333333%}.col-md-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66666667%;-ms-flex:0 0 66.66666667%;flex:0 0 66.66666667%;max-width:66.66666667%}.col-md-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333333%;-ms-flex:0 0 83.33333333%;flex:0 0 83.33333333%;max-width:83.33333333%}.col-md-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66666667%;-ms-flex:0 0 91.66666667%;flex:0 0 91.66666667%;max-width:91.66666667%}.col-md-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.order-md-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.order-md-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.order-md-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.order-md-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.order-md-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.order-md-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.order-md-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.order-md-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.order-md-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.order-md-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.order-md-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.order-md-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.order-md-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.order-md-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}}@media(min-width:992px){.col-lg{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-lg-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333333%;-ms-flex:0 0 8.33333333%;flex:0 0 8.33333333%;max-width:8.33333333%}.col-lg-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66666667%;-ms-flex:0 0 16.66666667%;flex:0 0 16.66666667%;max-width:16.66666667%}.col-lg-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333333%;-ms-flex:0 0 33.33333333%;flex:0 0 33.33333333%;max-width:33.33333333%}.col-lg-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66666667%;-ms-flex:0 0 41.66666667%;flex:0 0 41.66666667%;max-width:41.66666667%}.col-lg-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333333%;-ms-flex:0 0 58.33333333%;flex:0 0 58.33333333%;max-width:58.33333333%}.col-lg-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66666667%;-ms-flex:0 0 66.66666667%;flex:0 0 66.66666667%;max-width:66.66666667%}.col-lg-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333333%;-ms-flex:0 0 83.33333333%;flex:0 0 83.33333333%;max-width:83.33333333%}.col-lg-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66666667%;-ms-flex:0 0 91.66666667%;flex:0 0 91.66666667%;max-width:91.66666667%}.col-lg-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.order-lg-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.order-lg-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.order-lg-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.order-lg-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.order-lg-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.order-lg-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.order-lg-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.order-lg-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.order-lg-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.order-lg-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.order-lg-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.order-lg-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.order-lg-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.order-lg-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}}@media(min-width:1200px){.col-xl{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-xl-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333333%;-ms-flex:0 0 8.33333333%;flex:0 0 8.33333333%;max-width:8.33333333%}.col-xl-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66666667%;-ms-flex:0 0 16.66666667%;flex:0 0 16.66666667%;max-width:16.66666667%}.col-xl-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333333%;-ms-flex:0 0 33.33333333%;flex:0 0 33.33333333%;max-width:33.33333333%}.col-xl-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66666667%;-ms-flex:0 0 41.66666667%;flex:0 0 41.66666667%;max-width:41.66666667%}.col-xl-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333333%;-ms-flex:0 0 58.33333333%;flex:0 0 58.33333333%;max-width:58.33333333%}.col-xl-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66666667%;-ms-flex:0 0 66.66666667%;flex:0 0 66.66666667%;max-width:66.66666667%}.col-xl-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333333%;-ms-flex:0 0 83.33333333%;flex:0 0 83.33333333%;max-width:83.33333333%}.col-xl-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66666667%;-ms-flex:0 0 91.66666667%;flex:0 0 91.66666667%;max-width:91.66666667%}.col-xl-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.order-xl-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.order-xl-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.order-xl-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.order-xl-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.order-xl-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.order-xl-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.order-xl-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.order-xl-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.order-xl-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.order-xl-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.order-xl-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.order-xl-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.order-xl-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.order-xl-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}}.table,.td-box .row.section>table,.td-content>table{width:100%;margin-bottom:1rem;background-color:transparent}.table th,.td-box .row.section>table th,.td-content>table th,.table td,.td-box .row.section>table td,.td-content>table td{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th,.td-box .row.section>table thead th,.td-content>table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody,.td-box .row.section>table tbody+tbody,.td-content>table tbody+tbody{border-top:2px solid #dee2e6}.table .table,.td-box .row.section>table .table,.td-content>table .table,.table .td-box .row.section>table,.td-box .table .row.section>table,.td-box .row.section>table .row.section>table,.td-content>table .td-box .row.section>table,.td-box .td-content>table .row.section>table,.table .td-content>table,.td-box .row.section>table .td-content>table,.td-content>table .td-content>table{background-color:#fff}.table-sm th,.table-sm td{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered th,.table-bordered td{border:1px solid #dee2e6}.table-bordered thead th,.table-bordered thead td{border-bottom-width:2px}.table-borderless th,.table-borderless td,.table-borderless thead th,.table-borderless tbody+tbody{border:0}.table-striped tbody tr:nth-of-type(odd),.td-box .row.section>table tbody tr:nth-of-type(odd),.td-content>table tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>th,.table-primary>td{background-color:#c5d3df}.table-hover .table-primary:hover{background-color:#b5c7d6}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#b5c7d6}.table-secondary,.table-secondary>th,.table-secondary>td{background-color:#ffe6c5}.table-hover .table-secondary:hover{background-color:#ffdbac}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#ffdbac}.table-success,.table-success>th,.table-success>td{background-color:#c7d8ff}.table-hover .table-success:hover{background-color:#aec6ff}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#aec6ff}.table-info,.table-info>th,.table-info>td{background-color:#edf6f6}.table-hover .table-info:hover{background-color:#dceeee}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#dceeee}.table-warning,.table-warning>th,.table-warning>td{background-color:#fad5d1}.table-hover .table-warning:hover{background-color:#f8c0ba}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#f8c0ba}.table-danger,.table-danger>th,.table-danger>td{background-color:#fad5d1}.table-hover .table-danger:hover{background-color:#f8c0ba}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f8c0ba}.table-light,.table-light>th,.table-light>td{background-color:#f3fcfa}.table-hover .table-light:hover{background-color:#dff7f2}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#dff7f2}.table-dark,.table-dark>th,.table-dark>td{background-color:#cac9cd}.table-hover .table-dark:hover{background-color:#bdbcc1}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#bdbcc1}.table-active,.table-active>th,.table-active>td{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th,.td-box .row.section>table .thead-dark th,.td-content>table .thead-dark th{color:#fff;background-color:#222;border-color:#353535}.table .thead-light th,.td-box .row.section>table .thead-light th,.td-content>table .thead-light th{color:#495057;background-color:#eee;border-color:#dee2e6}.table-dark{color:#fff;background-color:#222}.table-dark th,.table-dark td,.table-dark thead th{border-color:#353535}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd),.td-box .row.section>table.table-dark tbody tr:nth-of-type(odd),.td-content>table.table-dark tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{background-color:rgba(255,255,255,.075)}@media(max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-sm>.table-bordered{border:0}}@media(max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-md>.table-bordered{border:0}}@media(max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-lg>.table-bordered{border:0}}@media(max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-xl>.table-bordered{border:0}}.table-responsive,.td-box .row.section>table,.td-content>table{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive>.table-bordered,.td-box .row.section>table>.table-bordered,.td-content>table>.table-bordered{border:0}.form-control{display:block;width:100%;height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px);padding:.375rem .75rem;font-size:1rem;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border-radius:.25rem;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media screen and (prefers-reduced-motion:reduce){.form-control{-webkit-transition:none;-o-transition:none;transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#6fa3ce;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(48,99,142,.25);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(48,99,142,.25)}.form-control::-webkit-input-placeholder{color:#888;opacity:1}.form-control::-moz-placeholder{color:#888;opacity:1}.form-control:-ms-input-placeholder{color:#888;opacity:1}.form-control::placeholder{color:#888;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#eee;opacity:1}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:-webkit-calc(0.375rem + 1px);padding-top:calc(0.375rem + 1px);padding-bottom:-webkit-calc(0.375rem + 1px);padding-bottom:calc(0.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:-webkit-calc(0.5rem + 1px);padding-top:calc(0.5rem + 1px);padding-bottom:-webkit-calc(0.5rem + 1px);padding-bottom:calc(0.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:-webkit-calc(0.25rem + 1px);padding-top:calc(0.25rem + 1px);padding-bottom:-webkit-calc(0.25rem + 1px);padding-bottom:calc(0.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding-top:.375rem;padding-bottom:.375rem;margin-bottom:0;line-height:1.5;color:#222;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{height:-webkit-calc(1.8125rem + 2px);height:calc(1.8125rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:-webkit-calc(2.875rem + 2px);height:calc(2.875rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[size],select.form-control[multiple]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label{color:#888}.form-check-label{margin-bottom:0}.form-check-inline{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#3772ff}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(55,114,255,.9);border-radius:.25rem}.was-validated .form-control:valid,.form-control.is-valid,.was-validated .custom-select:valid,.custom-select.is-valid{border-color:#3772ff}.was-validated .form-control:valid:focus,.form-control.is-valid:focus,.was-validated .custom-select:valid:focus,.custom-select.is-valid:focus{border-color:#3772ff;-webkit-box-shadow:0 0 0 .2rem rgba(55,114,255,.25);box-shadow:0 0 0 .2rem rgba(55,114,255,.25)}.was-validated .form-control:valid~.valid-feedback,.was-validated .form-control:valid~.valid-tooltip,.form-control.is-valid~.valid-feedback,.form-control.is-valid~.valid-tooltip,.was-validated .custom-select:valid~.valid-feedback,.was-validated .custom-select:valid~.valid-tooltip,.custom-select.is-valid~.valid-feedback,.custom-select.is-valid~.valid-tooltip{display:block}.was-validated .form-control-file:valid~.valid-feedback,.was-validated .form-control-file:valid~.valid-tooltip,.form-control-file.is-valid~.valid-feedback,.form-control-file.is-valid~.valid-tooltip{display:block}.was-validated .form-check-input:valid~.form-check-label,.form-check-input.is-valid~.form-check-label{color:#3772ff}.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip,.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip{display:block}.was-validated .custom-control-input:valid~.custom-control-label,.custom-control-input.is-valid~.custom-control-label{color:#3772ff}.was-validated .custom-control-input:valid~.custom-control-label::before,.custom-control-input.is-valid~.custom-control-label::before{background-color:#b7ccff}.was-validated .custom-control-input:valid~.valid-feedback,.was-validated .custom-control-input:valid~.valid-tooltip,.custom-control-input.is-valid~.valid-feedback,.custom-control-input.is-valid~.valid-tooltip{display:block}.was-validated .custom-control-input:valid:checked~.custom-control-label::before,.custom-control-input.is-valid:checked~.custom-control-label::before{background:#6a96ff -webkit-gradient(linear,left top,left bottom,from(#80a6ff),to(#6a96ff)) repeat-x;background:#6a96ff -webkit-linear-gradient(top,#80a6ff,#6a96ff) repeat-x;background:#6a96ff -o-linear-gradient(top,#80a6ff,#6a96ff) repeat-x;background:#6a96ff linear-gradient(180deg,#80a6ff,#6a96ff) repeat-x}.was-validated .custom-control-input:valid:focus~.custom-control-label::before,.custom-control-input.is-valid:focus~.custom-control-label::before{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(55,114,255,.25);box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(55,114,255,.25)}.was-validated .custom-file-input:valid~.custom-file-label,.custom-file-input.is-valid~.custom-file-label{border-color:#3772ff}.was-validated .custom-file-input:valid~.custom-file-label::after,.custom-file-input.is-valid~.custom-file-label::after{border-color:inherit}.was-validated .custom-file-input:valid~.valid-feedback,.was-validated .custom-file-input:valid~.valid-tooltip,.custom-file-input.is-valid~.valid-feedback,.custom-file-input.is-valid~.valid-tooltip{display:block}.was-validated .custom-file-input:valid:focus~.custom-file-label,.custom-file-input.is-valid:focus~.custom-file-label{-webkit-box-shadow:0 0 0 .2rem rgba(55,114,255,.25);box-shadow:0 0 0 .2rem rgba(55,114,255,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#ed6a5a}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(237,106,90,.9);border-radius:.25rem}.was-validated .form-control:invalid,.form-control.is-invalid,.was-validated .custom-select:invalid,.custom-select.is-invalid{border-color:#ed6a5a}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus,.was-validated .custom-select:invalid:focus,.custom-select.is-invalid:focus{border-color:#ed6a5a;-webkit-box-shadow:0 0 0 .2rem rgba(237,106,90,.25);box-shadow:0 0 0 .2rem rgba(237,106,90,.25)}.was-validated .form-control:invalid~.invalid-feedback,.was-validated .form-control:invalid~.invalid-tooltip,.form-control.is-invalid~.invalid-feedback,.form-control.is-invalid~.invalid-tooltip,.was-validated .custom-select:invalid~.invalid-feedback,.was-validated .custom-select:invalid~.invalid-tooltip,.custom-select.is-invalid~.invalid-feedback,.custom-select.is-invalid~.invalid-tooltip{display:block}.was-validated .form-control-file:invalid~.invalid-feedback,.was-validated .form-control-file:invalid~.invalid-tooltip,.form-control-file.is-invalid~.invalid-feedback,.form-control-file.is-invalid~.invalid-tooltip{display:block}.was-validated .form-check-input:invalid~.form-check-label,.form-check-input.is-invalid~.form-check-label{color:#ed6a5a}.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip,.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip{display:block}.was-validated .custom-control-input:invalid~.custom-control-label,.custom-control-input.is-invalid~.custom-control-label{color:#ed6a5a}.was-validated .custom-control-input:invalid~.custom-control-label::before,.custom-control-input.is-invalid~.custom-control-label::before{background-color:#fad2cd}.was-validated .custom-control-input:invalid~.invalid-feedback,.was-validated .custom-control-input:invalid~.invalid-tooltip,.custom-control-input.is-invalid~.invalid-feedback,.custom-control-input.is-invalid~.invalid-tooltip{display:block}.was-validated .custom-control-input:invalid:checked~.custom-control-label::before,.custom-control-input.is-invalid:checked~.custom-control-label::before{background:#f29488 -webkit-gradient(linear,left top,left bottom,from(#f4a49a),to(#f29488)) repeat-x;background:#f29488 -webkit-linear-gradient(top,#f4a49a,#f29488) repeat-x;background:#f29488 -o-linear-gradient(top,#f4a49a,#f29488) repeat-x;background:#f29488 linear-gradient(180deg,#f4a49a,#f29488) repeat-x}.was-validated .custom-control-input:invalid:focus~.custom-control-label::before,.custom-control-input.is-invalid:focus~.custom-control-label::before{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(237,106,90,.25);box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(237,106,90,.25)}.was-validated .custom-file-input:invalid~.custom-file-label,.custom-file-input.is-invalid~.custom-file-label{border-color:#ed6a5a}.was-validated .custom-file-input:invalid~.custom-file-label::after,.custom-file-input.is-invalid~.custom-file-label::after{border-color:inherit}.was-validated .custom-file-input:invalid~.invalid-feedback,.was-validated .custom-file-input:invalid~.invalid-tooltip,.custom-file-input.is-invalid~.invalid-feedback,.custom-file-input.is-invalid~.invalid-tooltip{display:block}.was-validated .custom-file-input:invalid:focus~.custom-file-label,.custom-file-input.is-invalid:focus~.custom-file-label{-webkit-box-shadow:0 0 0 .2rem rgba(237,106,90,.25);box-shadow:0 0 0 .2rem rgba(237,106,90,.25)}.form-inline{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media(min-width:576px){.form-inline label{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .input-group,.form-inline .custom-select{width:auto}.form-inline .form-check{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;text-align:center;white-space:nowrap;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media screen and (prefers-reduced-motion:reduce){.btn{-webkit-transition:none;-o-transition:none;transition:none}}.btn:hover,.btn:focus{text-decoration:none}.btn:focus,.btn.focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(48,99,142,.25);box-shadow:0 0 0 .2rem rgba(48,99,142,.25)}.btn.disabled,.btn:disabled{opacity:.65;-webkit-box-shadow:none;box-shadow:none}.btn:not(:disabled):not(.disabled){cursor:pointer}.btn:not(:disabled):not(.disabled):active,.btn:not(:disabled):not(.disabled).active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn:not(:disabled):not(.disabled):active:focus,.btn:not(:disabled):not(.disabled).active:focus{-webkit-box-shadow:0 0 0 .2rem rgba(48,99,142,.25),inset 0 3px 5px rgba(0,0,0,.125);box-shadow:0 0 0 .2rem rgba(48,99,142,.25),inset 0 3px 5px rgba(0,0,0,.125)}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x;border-color:#30638e;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-primary:hover{color:#fff;background:#264f71 -webkit-gradient(linear,left top,left bottom,from(#476987),to(#264f71)) repeat-x;background:#264f71 -webkit-linear-gradient(top,#476987,#264f71) repeat-x;background:#264f71 -o-linear-gradient(top,#476987,#264f71) repeat-x;background:#264f71 linear-gradient(180deg,#476987,#264f71) repeat-x;border-color:#234868}.btn-primary:focus,.btn-primary.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(48,99,142,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(48,99,142,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#30638e;border-color:#30638e}.btn-primary:not(:disabled):not(.disabled):active,.btn-primary:not(:disabled):not(.disabled).active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#234868;background-image:none;border-color:#20425e}.btn-primary:not(:disabled):not(.disabled):active:focus,.btn-primary:not(:disabled):not(.disabled).active:focus,.show>.btn-primary.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(48,99,142,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(48,99,142,.5)}.btn-secondary{color:#fff;background:#FFA630 -webkit-gradient(linear,left top,left bottom,from(#ffb34f),to(#FFA630)) repeat-x;background:#ffa630 -webkit-linear-gradient(top,#ffb34f,#FFA630) repeat-x;background:#ffa630 -o-linear-gradient(top,#ffb34f,#FFA630) repeat-x;background:#ffa630 linear-gradient(180deg,#ffb34f,#FFA630) repeat-x;border-color:#ffa630;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-secondary:hover{color:#fff;background:#ff960a -webkit-gradient(linear,left top,left bottom,from(#ffa52f),to(#ff960a)) repeat-x;background:#ff960a -webkit-linear-gradient(top,#ffa52f,#ff960a) repeat-x;background:#ff960a -o-linear-gradient(top,#ffa52f,#ff960a) repeat-x;background:#ff960a linear-gradient(180deg,#ffa52f,#ff960a) repeat-x;border-color:#fc9000}.btn-secondary:focus,.btn-secondary.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(255,166,48,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(255,166,48,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#ffa630;border-color:#ffa630}.btn-secondary:not(:disabled):not(.disabled):active,.btn-secondary:not(:disabled):not(.disabled).active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#fc9000;background-image:none;border-color:#ef8800}.btn-secondary:not(:disabled):not(.disabled):active:focus,.btn-secondary:not(:disabled):not(.disabled).active:focus,.show>.btn-secondary.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(255,166,48,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(255,166,48,.5)}.btn-success{color:#fff;background:#3772FF -webkit-gradient(linear,left top,left bottom,from(#5587ff),to(#3772FF)) repeat-x;background:#3772ff -webkit-linear-gradient(top,#5587ff,#3772FF) repeat-x;background:#3772ff -o-linear-gradient(top,#5587ff,#3772FF) repeat-x;background:#3772ff linear-gradient(180deg,#5587ff,#3772FF) repeat-x;border-color:#3772ff;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-success:hover{color:#fff;background:#1157ff -webkit-gradient(linear,left top,left bottom,from(#3470ff),to(#1157ff)) repeat-x;background:#1157ff -webkit-linear-gradient(top,#3470ff,#1157ff) repeat-x;background:#1157ff -o-linear-gradient(top,#3470ff,#1157ff) repeat-x;background:#1157ff linear-gradient(180deg,#3470ff,#1157ff) repeat-x;border-color:#044eff}.btn-success:focus,.btn-success.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(55,114,255,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(55,114,255,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#3772ff;border-color:#3772ff}.btn-success:not(:disabled):not(.disabled):active,.btn-success:not(:disabled):not(.disabled).active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#044eff;background-image:none;border-color:#0049f6}.btn-success:not(:disabled):not(.disabled):active:focus,.btn-success:not(:disabled):not(.disabled).active:focus,.show>.btn-success.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(55,114,255,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(55,114,255,.5)}.btn-info{color:#222;background:#C0E0DE -webkit-gradient(linear,left top,left bottom,from(#c9e5e3),to(#C0E0DE)) repeat-x;background:#c0e0de -webkit-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x;background:#c0e0de -o-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x;background:#c0e0de linear-gradient(180deg,#c9e5e3,#C0E0DE) repeat-x;border-color:#c0e0de;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-info:hover{color:#fff;background:#a6d3d1 -webkit-gradient(linear,left top,left bottom,from(#b4dad8),to(#a6d3d1)) repeat-x;background:#a6d3d1 -webkit-linear-gradient(top,#b4dad8,#a6d3d1) repeat-x;background:#a6d3d1 -o-linear-gradient(top,#b4dad8,#a6d3d1) repeat-x;background:#a6d3d1 linear-gradient(180deg,#b4dad8,#a6d3d1) repeat-x;border-color:#9ecfcc}.btn-info:focus,.btn-info.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(192,224,222,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(192,224,222,.5)}.btn-info.disabled,.btn-info:disabled{color:#222;background-color:#c0e0de;border-color:#c0e0de}.btn-info:not(:disabled):not(.disabled):active,.btn-info:not(:disabled):not(.disabled).active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#9ecfcc;background-image:none;border-color:#95cbc8}.btn-info:not(:disabled):not(.disabled):active:focus,.btn-info:not(:disabled):not(.disabled).active:focus,.show>.btn-info.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(192,224,222,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(192,224,222,.5)}.btn-warning{color:#fff;background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x;border-color:#ed6a5a;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-warning:hover{color:#fff;background:#e94b38 -webkit-gradient(linear,left top,left bottom,from(#ed6655),to(#e94b38)) repeat-x;background:#e94b38 -webkit-linear-gradient(top,#ed6655,#e94b38) repeat-x;background:#e94b38 -o-linear-gradient(top,#ed6655,#e94b38) repeat-x;background:#e94b38 linear-gradient(180deg,#ed6655,#e94b38) repeat-x;border-color:#e8402c}.btn-warning:focus,.btn-warning.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(237,106,90,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(237,106,90,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#fff;background-color:#ed6a5a;border-color:#ed6a5a}.btn-warning:not(:disabled):not(.disabled):active,.btn-warning:not(:disabled):not(.disabled).active,.show>.btn-warning.dropdown-toggle{color:#fff;background-color:#e8402c;background-image:none;border-color:#e73621}.btn-warning:not(:disabled):not(.disabled):active:focus,.btn-warning:not(:disabled):not(.disabled).active:focus,.show>.btn-warning.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5)}.btn-danger{color:#fff;background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x;border-color:#ed6a5a;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger:hover{color:#fff;background:#e94b38 -webkit-gradient(linear,left top,left bottom,from(#ed6655),to(#e94b38)) repeat-x;background:#e94b38 -webkit-linear-gradient(top,#ed6655,#e94b38) repeat-x;background:#e94b38 -o-linear-gradient(top,#ed6655,#e94b38) repeat-x;background:#e94b38 linear-gradient(180deg,#ed6655,#e94b38) repeat-x;border-color:#e8402c}.btn-danger:focus,.btn-danger.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(237,106,90,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(237,106,90,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#ed6a5a;border-color:#ed6a5a}.btn-danger:not(:disabled):not(.disabled):active,.btn-danger:not(:disabled):not(.disabled).active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#e8402c;background-image:none;border-color:#e73621}.btn-danger:not(:disabled):not(.disabled):active:focus,.btn-danger:not(:disabled):not(.disabled).active:focus,.show>.btn-danger.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5)}.btn-light{color:#222;background:#D3F3EE -webkit-gradient(linear,left top,left bottom,from(#daf5f1),to(#D3F3EE)) repeat-x;background:#d3f3ee -webkit-linear-gradient(top,#daf5f1,#D3F3EE) repeat-x;background:#d3f3ee -o-linear-gradient(top,#daf5f1,#D3F3EE) repeat-x;background:#d3f3ee linear-gradient(180deg,#daf5f1,#D3F3EE) repeat-x;border-color:#d3f3ee;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-light:hover{color:#222;background:#b5ebe2 -webkit-gradient(linear,left top,left bottom,from(#c0eee7),to(#b5ebe2)) repeat-x;background:#b5ebe2 -webkit-linear-gradient(top,#c0eee7,#b5ebe2) repeat-x;background:#b5ebe2 -o-linear-gradient(top,#c0eee7,#b5ebe2) repeat-x;background:#b5ebe2 linear-gradient(180deg,#c0eee7,#b5ebe2) repeat-x;border-color:#abe8df}.btn-light:focus,.btn-light.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(211,243,238,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(211,243,238,.5)}.btn-light.disabled,.btn-light:disabled{color:#222;background-color:#d3f3ee;border-color:#d3f3ee}.btn-light:not(:disabled):not(.disabled):active,.btn-light:not(:disabled):not(.disabled).active,.show>.btn-light.dropdown-toggle{color:#222;background-color:#abe8df;background-image:none;border-color:#a1e5db}.btn-light:not(:disabled):not(.disabled):active:focus,.btn-light:not(:disabled):not(.disabled).active:focus,.show>.btn-light.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(211,243,238,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(211,243,238,.5)}.btn-dark{color:#fff;background:#403F4C -webkit-gradient(linear,left top,left bottom,from(#5d5c67),to(#403F4C)) repeat-x;background:#403f4c -webkit-linear-gradient(top,#5d5c67,#403F4C) repeat-x;background:#403f4c -o-linear-gradient(top,#5d5c67,#403F4C) repeat-x;background:#403f4c linear-gradient(180deg,#5d5c67,#403F4C) repeat-x;border-color:#403f4c;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-dark:hover{color:#fff;background:#2e2e37 -webkit-gradient(linear,left top,left bottom,from(#4e4d55),to(#2e2e37)) repeat-x;background:#2e2e37 -webkit-linear-gradient(top,#4e4d55,#2e2e37) repeat-x;background:#2e2e37 -o-linear-gradient(top,#4e4d55,#2e2e37) repeat-x;background:#2e2e37 linear-gradient(180deg,#4e4d55,#2e2e37) repeat-x;border-color:#292830}.btn-dark:focus,.btn-dark.focus{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(64,63,76,.5);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075),0 0 0 .2rem rgba(64,63,76,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#403f4c;border-color:#403f4c}.btn-dark:not(:disabled):not(.disabled):active,.btn-dark:not(:disabled):not(.disabled).active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#292830;background-image:none;border-color:#232229}.btn-dark:not(:disabled):not(.disabled):active:focus,.btn-dark:not(:disabled):not(.disabled).active:focus,.show>.btn-dark.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(64,63,76,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(64,63,76,.5)}.btn-outline-primary{color:#30638e;background-color:transparent;background-image:none;border-color:#30638e}.btn-outline-primary:hover{color:#fff;background-color:#30638e;border-color:#30638e}.btn-outline-primary:focus,.btn-outline-primary.focus{-webkit-box-shadow:0 0 0 .2rem rgba(48,99,142,.5);box-shadow:0 0 0 .2rem rgba(48,99,142,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#30638e;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled):active,.btn-outline-primary:not(:disabled):not(.disabled).active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#30638e;border-color:#30638e}.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(48,99,142,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(48,99,142,.5)}.btn-outline-secondary{color:#ffa630;background-color:transparent;background-image:none;border-color:#ffa630}.btn-outline-secondary:hover{color:#fff;background-color:#ffa630;border-color:#ffa630}.btn-outline-secondary:focus,.btn-outline-secondary.focus{-webkit-box-shadow:0 0 0 .2rem rgba(255,166,48,.5);box-shadow:0 0 0 .2rem rgba(255,166,48,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#ffa630;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled):active,.btn-outline-secondary:not(:disabled):not(.disabled).active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#ffa630;border-color:#ffa630}.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(255,166,48,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(255,166,48,.5)}.btn-outline-success{color:#3772ff;background-color:transparent;background-image:none;border-color:#3772ff}.btn-outline-success:hover{color:#fff;background-color:#3772ff;border-color:#3772ff}.btn-outline-success:focus,.btn-outline-success.focus{-webkit-box-shadow:0 0 0 .2rem rgba(55,114,255,.5);box-shadow:0 0 0 .2rem rgba(55,114,255,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#3772ff;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled):active,.btn-outline-success:not(:disabled):not(.disabled).active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#3772ff;border-color:#3772ff}.btn-outline-success:not(:disabled):not(.disabled):active:focus,.btn-outline-success:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-success.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(55,114,255,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(55,114,255,.5)}.btn-outline-info{color:#c0e0de;background-color:transparent;background-image:none;border-color:#c0e0de}.btn-outline-info:hover{color:#222;background-color:#c0e0de;border-color:#c0e0de}.btn-outline-info:focus,.btn-outline-info.focus{-webkit-box-shadow:0 0 0 .2rem rgba(192,224,222,.5);box-shadow:0 0 0 .2rem rgba(192,224,222,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#c0e0de;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled):active,.btn-outline-info:not(:disabled):not(.disabled).active,.show>.btn-outline-info.dropdown-toggle{color:#222;background-color:#c0e0de;border-color:#c0e0de}.btn-outline-info:not(:disabled):not(.disabled):active:focus,.btn-outline-info:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-info.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(192,224,222,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(192,224,222,.5)}.btn-outline-warning{color:#ed6a5a;background-color:transparent;background-image:none;border-color:#ed6a5a}.btn-outline-warning:hover{color:#fff;background-color:#ed6a5a;border-color:#ed6a5a}.btn-outline-warning:focus,.btn-outline-warning.focus{-webkit-box-shadow:0 0 0 .2rem rgba(237,106,90,.5);box-shadow:0 0 0 .2rem rgba(237,106,90,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ed6a5a;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled):active,.btn-outline-warning:not(:disabled):not(.disabled).active,.show>.btn-outline-warning.dropdown-toggle{color:#fff;background-color:#ed6a5a;border-color:#ed6a5a}.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5)}.btn-outline-danger{color:#ed6a5a;background-color:transparent;background-image:none;border-color:#ed6a5a}.btn-outline-danger:hover{color:#fff;background-color:#ed6a5a;border-color:#ed6a5a}.btn-outline-danger:focus,.btn-outline-danger.focus{-webkit-box-shadow:0 0 0 .2rem rgba(237,106,90,.5);box-shadow:0 0 0 .2rem rgba(237,106,90,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#ed6a5a;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled):active,.btn-outline-danger:not(:disabled):not(.disabled).active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#ed6a5a;border-color:#ed6a5a}.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(237,106,90,.5)}.btn-outline-light{color:#d3f3ee;background-color:transparent;background-image:none;border-color:#d3f3ee}.btn-outline-light:hover{color:#222;background-color:#d3f3ee;border-color:#d3f3ee}.btn-outline-light:focus,.btn-outline-light.focus{-webkit-box-shadow:0 0 0 .2rem rgba(211,243,238,.5);box-shadow:0 0 0 .2rem rgba(211,243,238,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#d3f3ee;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled):active,.btn-outline-light:not(:disabled):not(.disabled).active,.show>.btn-outline-light.dropdown-toggle{color:#222;background-color:#d3f3ee;border-color:#d3f3ee}.btn-outline-light:not(:disabled):not(.disabled):active:focus,.btn-outline-light:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-light.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(211,243,238,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(211,243,238,.5)}.btn-outline-dark{color:#403f4c;background-color:transparent;background-image:none;border-color:#403f4c}.btn-outline-dark:hover{color:#fff;background-color:#403f4c;border-color:#403f4c}.btn-outline-dark:focus,.btn-outline-dark.focus{-webkit-box-shadow:0 0 0 .2rem rgba(64,63,76,.5);box-shadow:0 0 0 .2rem rgba(64,63,76,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#403f4c;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled):active,.btn-outline-dark:not(:disabled):not(.disabled).active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#403f4c;border-color:#403f4c}.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(64,63,76,.5);box-shadow:inset 0 3px 5px rgba(0,0,0,.125),0 0 0 .2rem rgba(64,63,76,.5)}.btn-link{font-weight:400;color:#3176d9;background-color:transparent}.btn-link:hover{color:#1e53a0;text-decoration:none;background-color:transparent;border-color:transparent}.btn-link:focus,.btn-link.focus{text-decoration:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link:disabled,.btn-link.disabled{color:#888;pointer-events:none}.btn-lg,.btn-group-lg>.btn{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-sm,.btn-group-sm>.btn{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}@media screen and (prefers-reduced-motion:reduce){.fade{-webkit-transition:none;-o-transition:none;transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}@media screen and (prefers-reduced-motion:reduce){.collapsing{-webkit-transition:none;-o-transition:none;transition:none}}.dropup,.dropright,.dropdown,.dropleft{position:relative}.dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#222;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;-webkit-box-shadow:0 .5rem 1rem rgba(0,0,0,.175);box-shadow:0 .5rem 1rem rgba(0,0,0,.175)}.dropdown-menu-right{right:0;left:auto}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;width:0;height:0;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=top],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #eee}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#222;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:hover,.dropdown-item:focus{color:#151515;text-decoration:none;background:#f8f9fa -webkit-gradient(linear,left top,left bottom,from(#f9fafb),to(#f8f9fa)) repeat-x;background:#f8f9fa -webkit-linear-gradient(top,#f9fafb,#f8f9fa) repeat-x;background:#f8f9fa -o-linear-gradient(top,#f9fafb,#f8f9fa) repeat-x;background:#f8f9fa linear-gradient(180deg,#f9fafb,#f8f9fa) repeat-x}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x}.dropdown-item.disabled,.dropdown-item:disabled{color:#888;background-color:transparent;background-image:none}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#888;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#222}.btn-group,.btn-group-vertical{position:relative;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover{z-index:1}.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn.active{z-index:1}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group,.btn-group-vertical .btn+.btn,.btn-group-vertical .btn+.btn-group,.btn-group-vertical .btn-group+.btn,.btn-group-vertical .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:not(:last-child):not(.dropdown-toggle),.btn-group>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:not(:first-child),.btn-group>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-lg+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group.show .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.show .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn-group-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.btn-group-vertical .btn,.btn-group-vertical .btn-group{width:100%}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle),.btn-group-vertical>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.custom-select,.input-group>.custom-file{position:relative;-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;margin-bottom:0}.input-group>.form-control+.form-control,.input-group>.form-control+.custom-select,.input-group>.form-control+.custom-file,.input-group>.custom-select+.form-control,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.custom-file,.input-group>.custom-file+.form-control,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.custom-file{margin-left:-1px}.input-group>.form-control:focus,.input-group>.custom-select:focus,.input-group>.custom-file .custom-file-input:focus~.custom-file-label{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.form-control:not(:last-child),.input-group>.custom-select:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.form-control:not(:first-child),.input-group>.custom-select:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-prepend,.input-group-append{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.input-group-prepend .btn,.input-group-append .btn{position:relative;z-index:2}.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.input-group-text,.input-group-append .input-group-text+.btn{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#eee;border:1px solid #ccc;border-radius:.25rem}.input-group-text input[type=radio],.input-group-text input[type=checkbox]{margin-top:0}.input-group-lg>.form-control,.input-group-lg>.input-group-prepend>.input-group-text,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-append>.btn{height:-webkit-calc(2.875rem + 2px);height:calc(2.875rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.form-control,.input-group-sm>.input-group-prepend>.input-group-text,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-append>.btn{height:-webkit-calc(1.8125rem + 2px);height:calc(1.8125rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text,.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;z-index:-1;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x;-webkit-box-shadow:none;box-shadow:none}.custom-control-input:focus~.custom-control-label::before{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(48,99,142,.25);box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(48,99,142,.25)}.custom-control-input:active~.custom-control-label::before{color:#fff;background-color:#95bbdb;-webkit-box-shadow:none;box-shadow:none}.custom-control-input:disabled~.custom-control-label{color:#888}.custom-control-input:disabled~.custom-control-label::before{background-color:#eee}.custom-control-label{position:relative;margin-bottom:0}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#dee2e6;-webkit-box-shadow:inset 0 .25rem .25rem rgba(0,0,0,.1);box-shadow:inset 0 .25rem .25rem rgba(0,0,0,.1)}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background-repeat:no-repeat;background-position:50%;-webkit-background-size:50% 50%;background-size:50% 50%}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::before{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA4IDgiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik02LjU2NC43NWwtMy41OSAzLjYxMi0xLjUzOC0xLjU1TDAgNC4yNiAyLjk3NCA3LjI1IDggMi4xOTN6Ii8+PC9zdmc+)}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x;-webkit-box-shadow:none;box-shadow:none}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0IDQiPjxwYXRoIHN0cm9rZT0iI2ZmZiIgZD0iTTAgMmg0Ii8+PC9zdmc+)}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(48,99,142,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(48,99,142,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::before{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii00IC00IDggOCI+PGNpcmNsZSByPSIzIiBmaWxsPSIjZmZmIi8+PC9zdmc+)}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(48,99,142,.5)}.custom-select{display:inline-block;width:100%;height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px);padding:.375rem 1.75rem .375rem .75rem;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0IDUiPjxwYXRoIGZpbGw9IiMzMzMiIGQ9Ik0yIDAgMCAyaDR6bTAgNUwwIDNoNHoiLz48L3N2Zz4=) no-repeat 100% .75rem 50%;-webkit-background-size:8px 10px;background-size:8px 10px;border:1px solid #ccc;border-radius:.25rem;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.075);box-shadow:inset 0 1px 2px rgba(0,0,0,.075);-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#6fa3ce;outline:0;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.075),0 0 0 .2rem rgba(111,163,206,.5);box-shadow:inset 0 1px 2px rgba(0,0,0,.075),0 0 0 .2rem rgba(111,163,206,.5)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#888;background-color:#eee}.custom-select::-ms-expand{opacity:0}.custom-select-sm{height:-webkit-calc(1.8125rem + 2px);height:calc(1.8125rem + 2px);padding-top:.375rem;padding-bottom:.375rem;font-size:75%}.custom-select-lg{height:-webkit-calc(2.875rem + 2px);height:calc(2.875rem + 2px);padding-top:.375rem;padding-bottom:.375rem;font-size:125%}.custom-file{position:relative;display:inline-block;width:100%;height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px);margin:0;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#6fa3ce;-webkit-box-shadow:0 0 0 .2rem rgba(48,99,142,.25);box-shadow:0 0 0 .2rem rgba(48,99,142,.25)}.custom-file-input:focus~.custom-file-label::after{border-color:#6fa3ce}.custom-file-input:disabled~.custom-file-label{background-color:#eee}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px);padding:.375rem .75rem;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ccc;border-radius:.25rem;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:2.25rem;padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background:#eee -webkit-gradient(linear,left top,left bottom,from(#f1f1f1),to(#eee)) repeat-x;background:#eee -webkit-linear-gradient(top,#f1f1f1,#eee) repeat-x;background:#eee -o-linear-gradient(top,#f1f1f1,#eee) repeat-x;background:#eee linear-gradient(180deg,#f1f1f1,#eee) repeat-x;border-left:1px solid #ccc;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;padding-left:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:none}.custom-range:focus::-webkit-slider-thumb{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(48,99,142,.25);box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(48,99,142,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(48,99,142,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(48,99,142,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x;border:0;border-radius:1rem;-webkit-box-shadow:0 .1rem .25rem rgba(0,0,0,.1);box-shadow:0 .1rem .25rem rgba(0,0,0,.1);-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media screen and (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;-o-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background:#95bbdb -webkit-gradient(linear,left top,left bottom,from(#a5c5e1),to(#95bbdb)) repeat-x;background:#95bbdb -webkit-linear-gradient(top,#a5c5e1,#95bbdb) repeat-x;background:#95bbdb linear-gradient(180deg,#a5c5e1,#95bbdb) repeat-x}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem;-webkit-box-shadow:inset 0 .25rem .25rem rgba(0,0,0,.1);box-shadow:inset 0 .25rem .25rem rgba(0,0,0,.1)}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x;border:0;border-radius:1rem;box-shadow:0 .1rem .25rem rgba(0,0,0,.1);-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media screen and (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-webkit-transition:none;-o-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background:#95bbdb linear-gradient(180deg,#a5c5e1,#95bbdb) repeat-x}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem;box-shadow:inset 0 .25rem .25rem rgba(0,0,0,.1)}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x;border:0;border-radius:1rem;box-shadow:0 .1rem .25rem rgba(0,0,0,.1);-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;appearance:none}@media screen and (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-webkit-transition:none;-o-transition:none;transition:none}}.custom-range::-ms-thumb:active{background:#95bbdb linear-gradient(180deg,#a5c5e1,#95bbdb) repeat-x}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem;box-shadow:inset 0 .25rem .25rem rgba(0,0,0,.1)}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-control-label::before,.custom-file-label,.custom-select{-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media screen and (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{-webkit-transition:none;-o-transition:none;transition:none}}.nav{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:hover,.nav-link:focus{text-decoration:none}.nav-link.disabled{color:#888}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:hover,.nav-tabs .nav-link:focus{border-color:#eee #eee #dee2e6}.nav-tabs .nav-link.disabled{color:#888;background-color:transparent;border-color:transparent}.nav-tabs .nav-link.active,.nav-tabs .nav-item.show .nav-link{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#30638e}.nav-fill .nav-item{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar>.container,.navbar>.container-fluid{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-nav{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-webkit-flex-basis:100%;-ms-flex-preferred-size:100%;flex-basis:100%;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:hover,.navbar-toggler:focus{text-decoration:none}.navbar-toggler:not(:disabled):not(.disabled){cursor:pointer}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat 50%;-webkit-background-size:100% 100%;background-size:100% 100%}@media(max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{padding-right:0;padding-left:0}}@media(min-width:576px){.navbar-expand-sm{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media(max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{padding-right:0;padding-left:0}}@media(min-width:768px){.navbar-expand-md{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media(max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{padding-right:0;padding-left:0}}@media(min-width:992px){.navbar-expand-lg{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media(max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{padding-right:0;padding-left:0}}@media(min-width:1200px){.navbar-expand-xl{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:hover,.navbar-light .navbar-brand:focus{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:hover,.navbar-light .navbar-nav .nav-link:focus{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .show>.nav-link,.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .nav-link.active{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMzAgMzAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggc3Ryb2tlPSJyZ2JhKDAsIDAsIDAsIDAuNSkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIGQ9Ik00IDdoMjJNNCAxNWgyMk00IDIzaDIyIi8+PC9zdmc+)}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:hover,.navbar-light .navbar-text a:focus{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:hover,.navbar-dark .navbar-brand:focus{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link:hover,.navbar-dark .navbar-nav .nav-link:focus{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .show>.nav-link,.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .nav-link.active{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.75);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMzAgMzAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggc3Ryb2tlPSJyZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNzUpIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBkPSJNNCA3aDIyTTQgMTVoMjJNNCAyM2gyMiIvPjwvc3ZnPg==)}.navbar-dark .navbar-text{color:rgba(255,255,255,.75)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:hover,.navbar-dark .navbar-text a:focus{color:#fff}.card,.td-content .highlight{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr,.td-content .highlight>hr{margin-right:0;margin-left:0}.card>.list-group:first-child .list-group-item:first-child,.td-content .highlight>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child,.td-content .highlight>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-body{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:-webkit-calc(0.25rem - 1px) -webkit-calc(0.25rem - 1px) 0 0;border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 -webkit-calc(0.25rem - 1px) -webkit-calc(0.25rem - 1px);border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img{width:100%;border-radius:-webkit-calc(0.25rem - 1px);border-radius:calc(0.25rem - 1px)}.card-img-top{width:100%;border-top-left-radius:-webkit-calc(0.25rem - 1px);border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:-webkit-calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.card-img-bottom{width:100%;border-bottom-right-radius:-webkit-calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px);border-bottom-left-radius:-webkit-calc(0.25rem - 1px);border-bottom-left-radius:calc(0.25rem - 1px)}.card-deck{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.card-deck .card,.card-deck .td-content .highlight,.td-content .card-deck .highlight{margin-bottom:15px}@media(min-width:576px){.card-deck{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card,.card-deck .td-content .highlight,.td-content .card-deck .highlight{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1 0 0%;-ms-flex:1 0 0%;flex:1 0 0%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.card-group>.card,.td-content .card-group>.highlight{margin-bottom:15px}@media(min-width:576px){.card-group{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card,.td-content .card-group>.highlight{-webkit-box-flex:1;-webkit-flex:1 0 0%;-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card,.td-content .card-group>.highlight+.card,.td-content .card-group>.card+.highlight,.td-content .card-group>.highlight+.highlight{margin-left:0;border-left:0}.card-group>.card:first-child,.td-content .card-group>.highlight:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:first-child .card-img-top,.td-content .card-group>.highlight:first-child .card-img-top,.card-group>.card:first-child .card-header,.td-content .card-group>.highlight:first-child .card-header{border-top-right-radius:0}.card-group>.card:first-child .card-img-bottom,.td-content .card-group>.highlight:first-child .card-img-bottom,.card-group>.card:first-child .card-footer,.td-content .card-group>.highlight:first-child .card-footer{border-bottom-right-radius:0}.card-group>.card:last-child,.td-content .card-group>.highlight:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:last-child .card-img-top,.td-content .card-group>.highlight:last-child .card-img-top,.card-group>.card:last-child .card-header,.td-content .card-group>.highlight:last-child .card-header{border-top-left-radius:0}.card-group>.card:last-child .card-img-bottom,.td-content .card-group>.highlight:last-child .card-img-bottom,.card-group>.card:last-child .card-footer,.td-content .card-group>.highlight:last-child .card-footer{border-bottom-left-radius:0}.card-group>.card:only-child,.td-content .card-group>.highlight:only-child{border-radius:.25rem}.card-group>.card:only-child .card-img-top,.td-content .card-group>.highlight:only-child .card-img-top,.card-group>.card:only-child .card-header,.td-content .card-group>.highlight:only-child .card-header{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-group>.card:only-child .card-img-bottom,.td-content .card-group>.highlight:only-child .card-img-bottom,.card-group>.card:only-child .card-footer,.td-content .card-group>.highlight:only-child .card-footer{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-group>.card:not(:first-child):not(:last-child):not(:only-child),.td-content .card-group>.highlight:not(:first-child):not(:last-child):not(:only-child){border-radius:0}.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-img-top,.td-content .card-group>.highlight:not(:first-child):not(:last-child):not(:only-child) .card-img-top,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom,.td-content .card-group>.highlight:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-header,.td-content .card-group>.highlight:not(:first-child):not(:last-child):not(:only-child) .card-header,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-footer,.td-content .card-group>.highlight:not(:first-child):not(:last-child):not(:only-child) .card-footer{border-radius:0}}.card-columns .card,.card-columns .td-content .highlight,.td-content .card-columns .highlight{margin-bottom:.75rem}@media(min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card,.card-columns .td-content .highlight,.td-content .card-columns .highlight{display:inline-block;width:100%}}.accordion .card:not(:first-of-type):not(:last-of-type),.accordion .td-content .highlight:not(:first-of-type):not(:last-of-type),.td-content .accordion .highlight:not(:first-of-type):not(:last-of-type){border-bottom:0;border-radius:0}.accordion .card:not(:first-of-type) .card-header:first-child,.accordion .td-content .highlight:not(:first-of-type) .card-header:first-child,.td-content .accordion .highlight:not(:first-of-type) .card-header:first-child{border-radius:0}.accordion .card:first-of-type,.accordion .td-content .highlight:first-of-type,.td-content .accordion .highlight:first-of-type{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion .card:last-of-type,.accordion .td-content .highlight:last-of-type,.td-content .accordion .highlight:last-of-type{border-top-left-radius:0;border-top-right-radius:0}.breadcrumb{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#eee;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;color:#888;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#888}.pagination{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#888;background-color:#fff;border:1px solid rgba(0,0,0,.1)}.page-link:hover{z-index:2;color:#1e53a0;text-decoration:none;background-color:#eee;border-color:#dee2e6}.page-link:focus{z-index:2;outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(48,99,142,.25);box-shadow:0 0 0 .2rem rgba(48,99,142,.25)}.page-link:not(:disabled):not(.disabled){cursor:pointer}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:1;color:#fff;background-color:#30638e;border-color:#2a567b}.page-item.disabled .page-link{color:#dee2e6;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#30638e}.badge-primary[href]:hover,.badge-primary[href]:focus{color:#fff;text-decoration:none;background-color:#234868}.badge-secondary{color:#fff;background-color:#ffa630}.badge-secondary[href]:hover,.badge-secondary[href]:focus{color:#fff;text-decoration:none;background-color:#fc9000}.badge-success{color:#fff;background-color:#3772ff}.badge-success[href]:hover,.badge-success[href]:focus{color:#fff;text-decoration:none;background-color:#044eff}.badge-info{color:#222;background-color:#c0e0de}.badge-info[href]:hover,.badge-info[href]:focus{color:#222;text-decoration:none;background-color:#9ecfcc}.badge-warning{color:#fff;background-color:#ed6a5a}.badge-warning[href]:hover,.badge-warning[href]:focus{color:#fff;text-decoration:none;background-color:#e8402c}.badge-danger{color:#fff;background-color:#ed6a5a}.badge-danger[href]:hover,.badge-danger[href]:focus{color:#fff;text-decoration:none;background-color:#e8402c}.badge-light{color:#222;background-color:#d3f3ee}.badge-light[href]:hover,.badge-light[href]:focus{color:#222;text-decoration:none;background-color:#abe8df}.badge-dark{color:#fff;background-color:#403f4c}.badge-dark[href]:hover,.badge-dark[href]:focus{color:#fff;text-decoration:none;background-color:#292830}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#eee;border-radius:.3rem}@media(min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#19334a;background:#d6e0e8 -webkit-gradient(linear,left top,left bottom,from(#dce5eb),to(#d6e0e8)) repeat-x;background:#d6e0e8 -webkit-linear-gradient(top,#dce5eb,#d6e0e8) repeat-x;background:#d6e0e8 -o-linear-gradient(top,#dce5eb,#d6e0e8) repeat-x;background:#d6e0e8 linear-gradient(180deg,#dce5eb,#d6e0e8) repeat-x;border-color:#c5d3df}.alert-primary hr{border-top-color:#b5c7d6}.alert-primary .alert-link{color:#0c1924}.alert-secondary{color:#855619;background:#ffedd6 -webkit-gradient(linear,left top,left bottom,from(#fff0dc),to(#ffedd6)) repeat-x;background:#ffedd6 -webkit-linear-gradient(top,#fff0dc,#ffedd6) repeat-x;background:#ffedd6 -o-linear-gradient(top,#fff0dc,#ffedd6) repeat-x;background:#ffedd6 linear-gradient(180deg,#fff0dc,#ffedd6) repeat-x;border-color:#ffe6c5}.alert-secondary hr{border-top-color:#ffdbac}.alert-secondary .alert-link{color:#5a3a11}.alert-success{color:#1d3b85;background:#d7e3ff -webkit-gradient(linear,left top,left bottom,from(#dde7ff),to(#d7e3ff)) repeat-x;background:#d7e3ff -webkit-linear-gradient(top,#dde7ff,#d7e3ff) repeat-x;background:#d7e3ff -o-linear-gradient(top,#dde7ff,#d7e3ff) repeat-x;background:#d7e3ff linear-gradient(180deg,#dde7ff,#d7e3ff) repeat-x;border-color:#c7d8ff}.alert-success hr{border-top-color:#aec6ff}.alert-success .alert-link{color:#14285b}.alert-info{color:#647473;background:#f2f9f8 -webkit-gradient(linear,left top,left bottom,from(#f4faf9),to(#f2f9f8)) repeat-x;background:#f2f9f8 -webkit-linear-gradient(top,#f4faf9,#f2f9f8) repeat-x;background:#f2f9f8 -o-linear-gradient(top,#f4faf9,#f2f9f8) repeat-x;background:#f2f9f8 linear-gradient(180deg,#f4faf9,#f2f9f8) repeat-x;border-color:#edf6f6}.alert-info hr{border-top-color:#dceeee}.alert-info .alert-link{color:#4c5958}.alert-warning{color:#7b372f;background:#fbe1de -webkit-gradient(linear,left top,left bottom,from(#fce6e3),to(#fbe1de)) repeat-x;background:#fbe1de -webkit-linear-gradient(top,#fce6e3,#fbe1de) repeat-x;background:#fbe1de -o-linear-gradient(top,#fce6e3,#fbe1de) repeat-x;background:#fbe1de linear-gradient(180deg,#fce6e3,#fbe1de) repeat-x;border-color:#fad5d1}.alert-warning hr{border-top-color:#f8c0ba}.alert-warning .alert-link{color:#562721}.alert-danger{color:#7b372f;background:#fbe1de -webkit-gradient(linear,left top,left bottom,from(#fce6e3),to(#fbe1de)) repeat-x;background:#fbe1de -webkit-linear-gradient(top,#fce6e3,#fbe1de) repeat-x;background:#fbe1de -o-linear-gradient(top,#fce6e3,#fbe1de) repeat-x;background:#fbe1de linear-gradient(180deg,#fce6e3,#fbe1de) repeat-x;border-color:#fad5d1}.alert-danger hr{border-top-color:#f8c0ba}.alert-danger .alert-link{color:#562721}.alert-light{color:#6e7e7c;background:#f6fdfc -webkit-gradient(linear,left top,left bottom,from(#f7fdfc),to(#f6fdfc)) repeat-x;background:#f6fdfc -webkit-linear-gradient(top,#f7fdfc,#f6fdfc) repeat-x;background:#f6fdfc -o-linear-gradient(top,#f7fdfc,#f6fdfc) repeat-x;background:#f6fdfc linear-gradient(180deg,#f7fdfc,#f6fdfc) repeat-x;border-color:#f3fcfa}.alert-light hr{border-top-color:#dff7f2}.alert-light .alert-link{color:#566361}.alert-dark{color:#212128;background:#d9d9db -webkit-gradient(linear,left top,left bottom,from(#dfdfe0),to(#d9d9db)) repeat-x;background:#d9d9db -webkit-linear-gradient(top,#dfdfe0,#d9d9db) repeat-x;background:#d9d9db -o-linear-gradient(top,#dfdfe0,#d9d9db) repeat-x;background:#d9d9db linear-gradient(180deg,#dfdfe0,#d9d9db) repeat-x;border-color:#cac9cd}.alert-dark hr{border-top-color:#bdbcc1}.alert-dark .alert-link{color:#0a0a0c}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#eee;border-radius:.25rem;-webkit-box-shadow:inset 0 .1rem .1rem rgba(0,0,0,.1);box-shadow:inset 0 .1rem .1rem rgba(0,0,0,.1)}.progress-bar{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;color:#fff;text-align:center;white-space:nowrap;background-color:#30638e;-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}@media screen and (prefers-reduced-motion:reduce){.progress-bar{-webkit-transition:none;-o-transition:none;transition:none}}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:1rem 1rem;background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;-o-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}.media{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start}.media-body{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.list-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:hover,.list-group-item-action:focus{color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#222;background-color:#eee}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;margin-bottom:-1px;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item:hover,.list-group-item:focus{z-index:1;text-decoration:none}.list-group-item.disabled,.list-group-item:disabled{color:#888;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#30638e;border-color:#30638e}.list-group-flush .list-group-item{border-right:0;border-left:0;border-radius:0}.list-group-flush:first-child .list-group-item:first-child{border-top:0}.list-group-flush:last-child .list-group-item:last-child{border-bottom:0}.list-group-item-primary{color:#19334a;background-color:#c5d3df}.list-group-item-primary.list-group-item-action:hover,.list-group-item-primary.list-group-item-action:focus{color:#19334a;background-color:#b5c7d6}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#19334a;border-color:#19334a}.list-group-item-secondary{color:#855619;background-color:#ffe6c5}.list-group-item-secondary.list-group-item-action:hover,.list-group-item-secondary.list-group-item-action:focus{color:#855619;background-color:#ffdbac}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#855619;border-color:#855619}.list-group-item-success{color:#1d3b85;background-color:#c7d8ff}.list-group-item-success.list-group-item-action:hover,.list-group-item-success.list-group-item-action:focus{color:#1d3b85;background-color:#aec6ff}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#1d3b85;border-color:#1d3b85}.list-group-item-info{color:#647473;background-color:#edf6f6}.list-group-item-info.list-group-item-action:hover,.list-group-item-info.list-group-item-action:focus{color:#647473;background-color:#dceeee}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#647473;border-color:#647473}.list-group-item-warning{color:#7b372f;background-color:#fad5d1}.list-group-item-warning.list-group-item-action:hover,.list-group-item-warning.list-group-item-action:focus{color:#7b372f;background-color:#f8c0ba}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#7b372f;border-color:#7b372f}.list-group-item-danger{color:#7b372f;background-color:#fad5d1}.list-group-item-danger.list-group-item-action:hover,.list-group-item-danger.list-group-item-action:focus{color:#7b372f;background-color:#f8c0ba}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#7b372f;border-color:#7b372f}.list-group-item-light{color:#6e7e7c;background-color:#f3fcfa}.list-group-item-light.list-group-item-action:hover,.list-group-item-light.list-group-item-action:focus{color:#6e7e7c;background-color:#dff7f2}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#6e7e7c;border-color:#6e7e7c}.list-group-item-dark{color:#212128;background-color:#cac9cd}.list-group-item-dark.list-group-item-action:hover,.list-group-item-dark.list-group-item-action:focus{color:#212128;background-color:#bdbcc1}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#212128;border-color:#212128}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:not(:disabled):not(.disabled){cursor:pointer}.close:not(:disabled):not(.disabled):hover,.close:not(:disabled):not(.disabled):focus{color:#000;text-decoration:none;opacity:.75}button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out,-o-transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}@media screen and (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{-webkit-transition:none;-o-transition:none;transition:none}}.modal.show .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-dialog-centered{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;min-height:-webkit-calc(100% - (0.5rem * 2));min-height:calc(100% - (0.5rem * 2))}.modal-dialog-centered::before{display:block;height:-webkit-calc(100vh - (0.5rem * 2));height:calc(100vh - (0.5rem * 2));content:""}.modal-content{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;-webkit-box-shadow:0 .25rem .5rem rgba(0,0,0,.5);box-shadow:0 .25rem .5rem rgba(0,0,0,.5);outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;padding:1rem;border-bottom:1px solid #eee;border-top-left-radius:.3rem;border-top-right-radius:.3rem}.modal-header .close{padding:1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;padding:1rem;border-top:1px solid #eee}.modal-footer>:not(:first-child){margin-left:.25rem}.modal-footer>:not(:last-child){margin-right:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media(min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-centered{min-height:-webkit-calc(100% - (1.75rem * 2));min-height:calc(100% - (1.75rem * 2))}.modal-dialog-centered::before{height:-webkit-calc(100vh - (1.75rem * 2));height:calc(100vh - (1.75rem * 2))}.modal-content{-webkit-box-shadow:0 .5rem 1rem rgba(0,0,0,.5);box-shadow:0 .5rem 1rem rgba(0,0,0,.5)}.modal-sm{max-width:300px}}@media(min-width:992px){.modal-lg{max-width:800px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:open sans,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-top,.bs-tooltip-auto[x-placement^=top]{padding:.4rem 0}.bs-tooltip-top .arrow,.bs-tooltip-auto[x-placement^=top] .arrow{bottom:0}.bs-tooltip-top .arrow::before,.bs-tooltip-auto[x-placement^=top] .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-right,.bs-tooltip-auto[x-placement^=right]{padding:0 .4rem}.bs-tooltip-right .arrow,.bs-tooltip-auto[x-placement^=right] .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-right .arrow::before,.bs-tooltip-auto[x-placement^=right] .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-bottom,.bs-tooltip-auto[x-placement^=bottom]{padding:.4rem 0}.bs-tooltip-bottom .arrow,.bs-tooltip-auto[x-placement^=bottom] .arrow{top:0}.bs-tooltip-bottom .arrow::before,.bs-tooltip-auto[x-placement^=bottom] .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-left,.bs-tooltip-auto[x-placement^=left]{padding:0 .4rem}.bs-tooltip-left .arrow,.bs-tooltip-auto[x-placement^=left] .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-left .arrow::before,.bs-tooltip-auto[x-placement^=left] .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:open sans,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;-webkit-box-shadow:0 .25rem .5rem rgba(0,0,0,.2);box-shadow:0 .25rem .5rem rgba(0,0,0,.2)}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::before,.popover .arrow::after{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-top,.bs-popover-auto[x-placement^=top]{margin-bottom:.5rem}.bs-popover-top .arrow,.bs-popover-auto[x-placement^=top] .arrow{bottom:-webkit-calc((0.5rem + 1px) * -1);bottom:calc((0.5rem + 1px) * -1)}.bs-popover-top .arrow::before,.bs-popover-auto[x-placement^=top] .arrow::before,.bs-popover-top .arrow::after,.bs-popover-auto[x-placement^=top] .arrow::after{border-width:.5rem .5rem 0}.bs-popover-top .arrow::before,.bs-popover-auto[x-placement^=top] .arrow::before{bottom:0;border-top-color:rgba(0,0,0,.25)}.bs-popover-top .arrow::after,.bs-popover-auto[x-placement^=top] .arrow::after{bottom:1px;border-top-color:#fff}.bs-popover-right,.bs-popover-auto[x-placement^=right]{margin-left:.5rem}.bs-popover-right .arrow,.bs-popover-auto[x-placement^=right] .arrow{left:-webkit-calc((0.5rem + 1px) * -1);left:calc((0.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-right .arrow::before,.bs-popover-auto[x-placement^=right] .arrow::before,.bs-popover-right .arrow::after,.bs-popover-auto[x-placement^=right] .arrow::after{border-width:.5rem .5rem .5rem 0}.bs-popover-right .arrow::before,.bs-popover-auto[x-placement^=right] .arrow::before{left:0;border-right-color:rgba(0,0,0,.25)}.bs-popover-right .arrow::after,.bs-popover-auto[x-placement^=right] .arrow::after{left:1px;border-right-color:#fff}.bs-popover-bottom,.bs-popover-auto[x-placement^=bottom]{margin-top:.5rem}.bs-popover-bottom .arrow,.bs-popover-auto[x-placement^=bottom] .arrow{top:-webkit-calc((0.5rem + 1px) * -1);top:calc((0.5rem + 1px) * -1)}.bs-popover-bottom .arrow::before,.bs-popover-auto[x-placement^=bottom] .arrow::before,.bs-popover-bottom .arrow::after,.bs-popover-auto[x-placement^=bottom] .arrow::after{border-width:0 .5rem .5rem}.bs-popover-bottom .arrow::before,.bs-popover-auto[x-placement^=bottom] .arrow::before{top:0;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-bottom .arrow::after,.bs-popover-auto[x-placement^=bottom] .arrow::after{top:1px;border-bottom-color:#fff}.bs-popover-bottom .popover-header::before,.bs-popover-auto[x-placement^=bottom] .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-left,.bs-popover-auto[x-placement^=left]{margin-right:.5rem}.bs-popover-left .arrow,.bs-popover-auto[x-placement^=left] .arrow{right:-webkit-calc((0.5rem + 1px) * -1);right:calc((0.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-left .arrow::before,.bs-popover-auto[x-placement^=left] .arrow::before,.bs-popover-left .arrow::after,.bs-popover-auto[x-placement^=left] .arrow::after{border-width:.5rem 0 .5rem .5rem}.bs-popover-left .arrow::before,.bs-popover-auto[x-placement^=left] .arrow::before{right:0;border-left-color:rgba(0,0,0,.25)}.bs-popover-left .arrow::after,.bs-popover-auto[x-placement^=left] .arrow::after{right:1px;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;color:inherit;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:-webkit-calc(0.3rem - 1px);border-top-left-radius:calc(0.3rem - 1px);border-top-right-radius:-webkit-calc(0.3rem - 1px);border-top-right-radius:calc(0.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#222}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-item{position:relative;display:none;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;width:100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-item.active,.carousel-item-next,.carousel-item-prev{display:block;-webkit-transition:-webkit-transform .6s ease;transition:-webkit-transform .6s ease;-o-transition:-o-transform .6s ease;transition:transform .6s ease;transition:transform .6s ease,-webkit-transform .6s ease,-o-transform .6s ease}@media screen and (prefers-reduced-motion:reduce){.carousel-item.active,.carousel-item-next,.carousel-item-prev{-webkit-transition:none;-o-transition:none;transition:none}}.carousel-item-next,.carousel-item-prev{position:absolute;top:0}.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translateX(0);-ms-transform:translateX(0);-o-transform:translateX(0);transform:translateX(0)}@supports((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-item-next,.active.carousel-item-right{-webkit-transform:translateX(100%);-ms-transform:translateX(100%);-o-transform:translateX(100%);transform:translateX(100%)}@supports((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-item-next,.active.carousel-item-right{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.carousel-item-prev,.active.carousel-item-left{-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);-o-transform:translateX(-100%);transform:translateX(-100%)}@supports((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-item-prev,.active.carousel-item-left{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.carousel-fade .carousel-item{opacity:0;-webkit-transition-duration:.6s;-o-transition-duration:.6s;transition-duration:.6s;-webkit-transition-property:opacity;-o-transition-property:opacity;transition-property:opacity}.carousel-fade .carousel-item.active,.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right{opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{opacity:0}.carousel-fade .carousel-item-next,.carousel-fade .carousel-item-prev,.carousel-fade .carousel-item.active,.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-prev{-webkit-transform:translateX(0);-ms-transform:translateX(0);-o-transform:translateX(0);transform:translateX(0)}@supports((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-fade .carousel-item-next,.carousel-fade .carousel-item-prev,.carousel-fade .carousel-item.active,.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-prev{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-control-prev,.carousel-control-next{position:absolute;top:0;bottom:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0;background:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,0.25)),to(rgba(0,0,0,0.001)));background:-webkit-linear-gradient(left,rgba(0,0,0,0.25),rgba(0,0,0,0.001));background:-o-linear-gradient(left,rgba(0,0,0,0.25),rgba(0,0,0,0.001));background:linear-gradient(90deg,rgba(0,0,0,0.25),rgba(0,0,0,0.001))}.carousel-control-next{right:0;background:-webkit-gradient(linear,right top,left top,from(rgba(0,0,0,0.25)),to(rgba(0,0,0,0.001)));background:-webkit-linear-gradient(right,rgba(0,0,0,0.25),rgba(0,0,0,0.001));background:-o-linear-gradient(right,rgba(0,0,0,0.25),rgba(0,0,0,0.001));background:linear-gradient(270deg,rgba(0,0,0,0.25),rgba(0,0,0,0.001))}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:20px;height:20px;background:transparent no-repeat 50%;-webkit-background-size:100% 100%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiNmZmYiIHZpZXdCb3g9IjAgMCA4IDgiPjxwYXRoIGQ9Ik01LjI1LjBsLTQgNCA0IDQgMS41LTEuNUw0LjI1IDRsMi41LTIuNUw1LjI1LjB6Ii8+PC9zdmc+)}.carousel-control-next-icon{background-image:url(data:image/svg+xml;charset=utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiNmZmYiIHZpZXdCb3g9IjAgMCA4IDgiPjxwYXRoIGQ9Ik0yLjc1LjBsLTEuNSAxLjVMMy43NSA0bC0yLjUgMi41TDIuNzUgOGw0LTQtNC00eiIvPjwvc3ZnPg==)}.carousel-indicators{position:absolute;right:0;bottom:10px;left:0;z-index:15;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{position:relative;-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:rgba(255,255,255,.5)}.carousel-indicators li::before{position:absolute;top:-10px;left:0;display:inline-block;width:100%;height:10px;content:""}.carousel-indicators li::after{position:absolute;bottom:-10px;left:0;display:inline-block;width:100%;height:10px;content:""}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#30638e!important}a.bg-primary:hover,a.bg-primary:focus,button.bg-primary:hover,button.bg-primary:focus{background-color:#234868!important}.bg-secondary{background-color:#ffa630!important}a.bg-secondary:hover,a.bg-secondary:focus,button.bg-secondary:hover,button.bg-secondary:focus{background-color:#fc9000!important}.bg-success{background-color:#3772ff!important}a.bg-success:hover,a.bg-success:focus,button.bg-success:hover,button.bg-success:focus{background-color:#044eff!important}.bg-info{background-color:#c0e0de!important}a.bg-info:hover,a.bg-info:focus,button.bg-info:hover,button.bg-info:focus{background-color:#9ecfcc!important}.bg-warning{background-color:#ed6a5a!important}a.bg-warning:hover,a.bg-warning:focus,button.bg-warning:hover,button.bg-warning:focus{background-color:#e8402c!important}.bg-danger{background-color:#ed6a5a!important}a.bg-danger:hover,a.bg-danger:focus,button.bg-danger:hover,button.bg-danger:focus{background-color:#e8402c!important}.bg-light{background-color:#d3f3ee!important}a.bg-light:hover,a.bg-light:focus,button.bg-light:hover,button.bg-light:focus{background-color:#abe8df!important}.bg-dark{background-color:#403f4c!important}a.bg-dark:hover,a.bg-dark:focus,button.bg-dark:hover,button.bg-dark:focus{background-color:#292830!important}.bg-gradient-primary{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x!important;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x!important}.bg-gradient-secondary{background:#FFA630 -webkit-gradient(linear,left top,left bottom,from(#ffb34f),to(#FFA630)) repeat-x!important;background:#ffa630 -webkit-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 -o-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 linear-gradient(180deg,#ffb34f,#FFA630) repeat-x!important}.bg-gradient-success{background:#3772FF -webkit-gradient(linear,left top,left bottom,from(#5587ff),to(#3772FF)) repeat-x!important;background:#3772ff -webkit-linear-gradient(top,#5587ff,#3772FF) repeat-x!important;background:#3772ff -o-linear-gradient(top,#5587ff,#3772FF) repeat-x!important;background:#3772ff linear-gradient(180deg,#5587ff,#3772FF) repeat-x!important}.bg-gradient-info{background:#C0E0DE -webkit-gradient(linear,left top,left bottom,from(#c9e5e3),to(#C0E0DE)) repeat-x!important;background:#c0e0de -webkit-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de -o-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de linear-gradient(180deg,#c9e5e3,#C0E0DE) repeat-x!important}.bg-gradient-warning{background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x!important;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x!important}.bg-gradient-danger{background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x!important;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x!important}.bg-gradient-light{background:#D3F3EE -webkit-gradient(linear,left top,left bottom,from(#daf5f1),to(#D3F3EE)) repeat-x!important;background:#d3f3ee -webkit-linear-gradient(top,#daf5f1,#D3F3EE) repeat-x!important;background:#d3f3ee -o-linear-gradient(top,#daf5f1,#D3F3EE) repeat-x!important;background:#d3f3ee linear-gradient(180deg,#daf5f1,#D3F3EE) repeat-x!important}.bg-gradient-dark{background:#403F4C -webkit-gradient(linear,left top,left bottom,from(#5d5c67),to(#403F4C)) repeat-x!important;background:#403f4c -webkit-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c -o-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c linear-gradient(180deg,#5d5c67,#403F4C) repeat-x!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#30638e!important}.border-secondary{border-color:#ffa630!important}.border-success{border-color:#3772ff!important}.border-info{border-color:#c0e0de!important}.border-warning{border-color:#ed6a5a!important}.border-danger{border-color:#ed6a5a!important}.border-light{border-color:#d3f3ee!important}.border-dark{border-color:#403f4c!important}.border-white{border-color:#fff!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-circle{border-radius:50%!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}@media(min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media(min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media(min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media(min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.85714286%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}@media(min-width:576px){.flex-sm-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media(min-width:768px){.flex-md-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media(min-width:992px){.flex-lg-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media(min-width:1200px){.flex-xl-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media(min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media(min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media(min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media(min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{-webkit-box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important;box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{-webkit-box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important;box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{-webkit-box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important;box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{-webkit-box-shadow:none!important;box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media(min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media(min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media(min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media(min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,liberation mono,courier new,monospace}.text-justify{text-align:justify!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media(min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media(min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media(min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media(min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#30638e!important}a.text-primary:hover,a.text-primary:focus{color:#234868!important}.text-secondary{color:#ffa630!important}a.text-secondary:hover,a.text-secondary:focus{color:#fc9000!important}.text-success{color:#3772ff!important}a.text-success:hover,a.text-success:focus{color:#044eff!important}.text-info{color:#c0e0de!important}a.text-info:hover,a.text-info:focus{color:#9ecfcc!important}.text-warning{color:#ed6a5a!important}a.text-warning:hover,a.text-warning:focus{color:#e8402c!important}.text-danger{color:#ed6a5a!important}a.text-danger:hover,a.text-danger:focus{color:#e8402c!important}.text-light{color:#d3f3ee!important}a.text-light:hover,a.text-light:focus{color:#abe8df!important}.text-dark{color:#403f4c!important}a.text-dark:hover,a.text-dark:focus{color:#292830!important}.text-body{color:#222!important}.text-muted{color:#888!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,*::before,*::after{text-shadow:none!important;-webkit-box-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}pre,blockquote{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table,.td-box .row.section>table,.td-content>table{border-collapse:collapse!important}.table td,.td-box .row.section>table td,.td-content>table td,.table th,.td-box .row.section>table th,.td-content>table th{background-color:#fff!important}.table-bordered th,.table-bordered td{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark th,.table-dark td,.table-dark thead th,.table-dark tbody+tbody{border-color:#dee2e6}.table .thead-dark th,.td-box .row.section>table .thead-dark th,.td-content>table .thead-dark th{color:inherit;border-color:#dee2e6}}/*!* Font Awesome Free 5.10.1 by @fontawesome - https://fontawesome.com +* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)*/.fa,.fas,.far,.fal,.fad,.fab{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:solid .08em #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fas.fa-pull-left,.far.fa-pull-left,.fal.fa-pull-left,.fab.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fas.fa-pull-right,.far.fa-pull-right,.fal.fa-pull-right,.fab.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;-o-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);-o-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-o-keyframes fa-spin{0%{-o-transform:rotate(0deg);transform:rotate(0deg)}100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);-o-transform:rotate(360deg);transform:rotate(360deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);-o-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(-1,-1);-ms-transform:scale(-1,-1);-o-transform:scale(-1,-1);transform:scale(-1,-1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-flip-both{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adobe:before{content:"\f778"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-atlassian:before{content:"\f77b"}.fa-atom:before{content:"\f5d2"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-baby:before{content:"\f77c"}.fa-baby-carriage:before{content:"\f77d"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-bacon:before{content:"\f7e5"}.fa-balance-scale:before{content:"\f24e"}.fa-balance-scale-left:before{content:"\f515"}.fa-balance-scale-right:before{content:"\f516"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-battle-net:before{content:"\f835"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bible:before{content:"\f647"}.fa-bicycle:before{content:"\f206"}.fa-biking:before{content:"\f84a"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-biohazard:before{content:"\f780"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blind:before{content:"\f29d"}.fa-blog:before{content:"\f781"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-dead:before{content:"\f6b7"}.fa-book-medical:before{content:"\f7e6"}.fa-book-open:before{content:"\f518"}.fa-book-reader:before{content:"\f5da"}.fa-bookmark:before{content:"\f02e"}.fa-bootstrap:before{content:"\f836"}.fa-border-all:before{content:"\f84c"}.fa-border-none:before{content:"\f850"}.fa-border-style:before{content:"\f853"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-bread-slice:before{content:"\f7ec"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-buffer:before{content:"\f837"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-business-time:before{content:"\f64a"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-day:before{content:"\f783"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-calendar-week:before{content:"\f784"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-campground:before{content:"\f6bb"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-candy-cane:before{content:"\f786"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-car-alt:before{content:"\f5de"}.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-side:before{content:"\f5e4"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-carrot:before{content:"\f787"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cash-register:before{content:"\f788"}.fa-cat:before{content:"\f6be"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-centos:before{content:"\f789"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-charging-station:before{content:"\f5e7"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-cheese:before{content:"\f7ef"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-chromecast:before{content:"\f838"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-city:before{content:"\f64f"}.fa-clinic-medical:before{content:"\f7f2"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-medical:before{content:"\f7f5"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-compress-arrows-alt:before{content:"\f78c"}.fa-concierge-bell:before{content:"\f562"}.fa-confluence:before{content:"\f78d"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-cotton-bureau:before{content:"\f89e"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-credit-card:before{content:"\f09d"}.fa-critical-role:before{content:"\f6c9"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-crutch:before{content:"\f7f7"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-delicious:before{content:"\f1a5"}.fa-democrat:before{content:"\f747"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dharmachakra:before{content:"\f655"}.fa-dhl:before{content:"\f790"}.fa-diagnoses:before{content:"\f470"}.fa-diaspora:before{content:"\f791"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-directions:before{content:"\f5eb"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dumpster:before{content:"\f793"}.fa-dumpster-fire:before{content:"\f794"}.fa-dungeon:before{content:"\f6d9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edit:before{content:"\f044"}.fa-egg:before{content:"\f7fb"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-ethernet:before{content:"\f796"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-evernote:before{content:"\f839"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fan:before{content:"\f863"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-fedex:before{content:"\f797"}.fa-fedora:before{content:"\f798"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-figma:before{content:"\f799"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-alt:before{content:"\f7e4"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-fist-raised:before{content:"\f6de"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-funnel-dollar:before{content:"\f662"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-gifts:before{content:"\f79c"}.fa-git:before{content:"\f1d3"}.fa-git-alt:before{content:"\f841"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-cheers:before{content:"\f79f"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glass-whiskey:before{content:"\f7a0"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-globe-europe:before{content:"\f7a2"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-lines:before{content:"\f7a4"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-guitar:before{content:"\f7a6"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hamburger:before{content:"\f805"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-middle-finger:before{content:"\f806"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-handshake:before{content:"\f2b5"}.fa-hanukiah:before{content:"\f6e6"}.fa-hard-hat:before{content:"\f807"}.fa-hashtag:before{content:"\f292"}.fa-hat-wizard:before{content:"\f6e8"}.fa-haykal:before{content:"\f666"}.fa-hdd:before{content:"\f0a0"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heart-broken:before{content:"\f7a9"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hiking:before{content:"\f6ec"}.fa-hippo:before{content:"\f6ed"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hockey-puck:before{content:"\f453"}.fa-holly-berry:before{content:"\f7aa"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-horse:before{content:"\f6f0"}.fa-horse-head:before{content:"\f7ab"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hot-tub:before{content:"\f593"}.fa-hotdog:before{content:"\f80f"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-house-damage:before{content:"\f6f1"}.fa-houzz:before{content:"\f27c"}.fa-hryvnia:before{content:"\f6f2"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-ice-cream:before{content:"\f810"}.fa-icicles:before{content:"\f7ad"}.fa-icons:before{content:"\f86d"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-igloo:before{content:"\f7ae"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-instagram:before{content:"\f16d"}.fa-intercom:before{content:"\f7af"}.fa-internet-explorer:before{content:"\f26b"}.fa-invision:before{content:"\f7b0"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itch-io:before{content:"\f83a"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi:before{content:"\f669"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-jira:before{content:"\f7b1"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-journal-whills:before{content:"\f66a"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaaba:before{content:"\f66b"}.fa-kaggle:before{content:"\f5fa"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-khanda:before{content:"\f66d"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laptop-medical:before{content:"\f812"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mail-bulk:before{content:"\f674"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-markdown:before{content:"\f60f"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mask:before{content:"\f6fa"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-mendeley:before{content:"\f7b3"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-meteor:before{content:"\f753"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mitten:before{content:"\f7b5"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mouse-pointer:before{content:"\f245"}.fa-mug-hot:before{content:"\f7b6"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-oil-can:before{content:"\f613"}.fa-old-republic:before{content:"\f510"}.fa-om:before{content:"\f679"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-osi:before{content:"\f41a"}.fa-otter:before{content:"\f700"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-pager:before{content:"\f815"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-pastafarianism:before{content:"\f67b"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-penny-arcade:before{content:"\f704"}.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-person-booth:before{content:"\f756"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-alt:before{content:"\f879"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-square-alt:before{content:"\f87b"}.fa-phone-volume:before{content:"\f2a0"}.fa-photo-video:before{content:"\f87c"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-pizza-slice:before{content:"\f818"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poll:before{content:"\f681"}.fa-poll-h:before{content:"\f682"}.fa-poo:before{content:"\f2fe"}.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-pray:before{content:"\f683"}.fa-praying-hands:before{content:"\f684"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-quran:before{content:"\f687"}.fa-r-project:before{content:"\f4f7"}.fa-radiation:before{content:"\f7b9"}.fa-radiation-alt:before{content:"\f7ba"}.fa-rainbow:before{content:"\f75b"}.fa-random:before{content:"\f074"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redhat:before{content:"\f7bc"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-remove-format:before{content:"\f87d"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-republican:before{content:"\f75e"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-restroom:before{content:"\f7bd"}.fa-retweet:before{content:"\f079"}.fa-rev:before{content:"\f5b2"}.fa-ribbon:before{content:"\f4d6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-route:before{content:"\f4d7"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-running:before{content:"\f70c"}.fa-rupee-sign:before{content:"\f156"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-salesforce:before{content:"\f83b"}.fa-sass:before{content:"\f41e"}.fa-satellite:before{content:"\f7bf"}.fa-satellite-dish:before{content:"\f7c0"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-scroll:before{content:"\f70e"}.fa-sd-card:before{content:"\f7c2"}.fa-search:before{content:"\f002"}.fa-search-dollar:before{content:"\f688"}.fa-search-location:before{content:"\f689"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-shapes:before{content:"\f61f"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-sim-card:before{content:"\f7c4"}.fa-simplybuilt:before{content:"\f215"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skating:before{content:"\f7c5"}.fa-sketch:before{content:"\f7c6"}.fa-skiing:before{content:"\f7c9"}.fa-skiing-nordic:before{content:"\f7ca"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-slash:before{content:"\f715"}.fa-sleigh:before{content:"\f7cc"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-sms:before{content:"\f7cd"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowboarding:before{content:"\f7ce"}.fa-snowflake:before{content:"\f2dc"}.fa-snowman:before{content:"\f7d0"}.fa-snowplow:before{content:"\f7d2"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-down-alt:before{content:"\f884"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-amount-up-alt:before{content:"\f885"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-sourcetree:before{content:"\f7d3"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-speaker-deck:before{content:"\f83c"}.fa-spell-check:before{content:"\f891"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-square-root-alt:before{content:"\f698"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stackpath:before{content:"\f842"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-suse:before{content:"\f7d6"}.fa-swatchbook:before{content:"\f5c3"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-symfony:before{content:"\f83d"}.fa-synagogue:before{content:"\f69b"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-tenge:before{content:"\f7d7"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-the-red-yeti:before{content:"\f69d"}.fa-theater-masks:before{content:"\f630"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-think-peaks:before{content:"\f731"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet:before{content:"\f7d8"}.fa-toilet-paper:before{content:"\f71e"}.fa-toolbox:before{content:"\f552"}.fa-tools:before{content:"\f7d9"}.fa-tooth:before{content:"\f5c9"}.fa-torah:before{content:"\f6a0"}.fa-torii-gate:before{content:"\f6a1"}.fa-tractor:before{content:"\f722"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-train:before{content:"\f238"}.fa-tram:before{content:"\f7da"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-trash-restore:before{content:"\f829"}.fa-trash-restore-alt:before{content:"\f82a"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-tripadvisor:before{content:"\f262"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-ubuntu:before{content:"\f7df"}.fa-uikit:before{content:"\f403"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-ups:before{content:"\f7e0"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-injured:before{content:"\f728"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-nurse:before{content:"\f82f"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-usps:before{content:"\f7e1"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-voicemail:before{content:"\f897"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-mute:before{content:"\f6a9"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vote-yea:before{content:"\f772"}.fa-vr-cardboard:before{content:"\f729"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-water:before{content:"\f773"}.fa-wave-square:before{content:"\f83e"}.fa-waze:before{content:"\f83f"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-wind:before{content:"\f72e"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yammer:before{content:"\f840"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yarn:before{content:"\f7e3"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}/*!* Font Awesome Free 5.10.1 by @fontawesome - https://fontawesome.com +* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)*/@font-face{font-family:'font awesome 5 free';font-style:normal;font-weight:900;font-display:auto;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.fas{font-family:'font awesome 5 free';font-weight:900}/*!* Font Awesome Free 5.10.1 by @fontawesome - https://fontawesome.com +* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)*/@font-face{font-family:'font awesome 5 brands';font-style:normal;font-weight:400;font-display:auto;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:'font awesome 5 brands'}.td-border-top{border:none;border-top:1px solid #eee}.td-border-none{border:none}.td-block-padding,.td-default main section{padding-top:4rem;padding-bottom:4rem}@media(min-width:768px){.td-block-padding,.td-default main section{padding-top:5rem;padding-bottom:5rem}}.td-overlay{position:relative}.td-overlay::after{content:"";position:absolute;top:0;right:0;bottom:0;left:0}.td-overlay--dark::after{background-color:rgba(64,63,76,.3)}.td-overlay--light::after{background-color:rgba(211,243,238,.3)}.td-overlay__inner{position:relative;z-index:1}@media(min-width:992px){.td-max-width-on-larger-screens,.td-content>pre,.td-content>.highlight,.td-content>.lead,.td-content>h1,.td-content>h2,.td-content>ul,.td-content>ol,.td-content>p,.td-content>blockquote,.td-content>dl dd,.td-content .footnotes,.td-content>.alert{max-width:80%}}.td-box--height-min{min-height:300px}.td-box--height-med{min-height:400px}.td-box--height-max{min-height:500px}.td-box--height-full{min-height:100vh}@media(min-width:768px){.td-box--height-min{min-height:450px}.td-box--height-med{min-height:500px}.td-box--height-max{min-height:650px}}.td-box .row.section{padding-left:5rem;padding-right:5rem;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.td-box .row{padding-left:5rem;padding-right:5rem;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.td-box.linkbox{padding:5rem}.td-box--0{color:#fff;background-color:#403f4c}.td-box--0 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#403f4c transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--0 p>a{color:#d9e5f8}.td-box--10.td-box--gradient{background:#403F4C -webkit-gradient(linear,left top,left bottom,from(#5d5c67),to(#403F4C)) repeat-x!important;background:#403f4c -webkit-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c -o-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c linear-gradient(180deg,#5d5c67,#403F4C) repeat-x!important}.td-box--1{color:#fff;background-color:#30638e}.td-box--1 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#30638e transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--1 p>a{color:#cadcf5}.td-box--11.td-box--gradient{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x!important;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x!important}.td-box--2{color:#fff;background-color:#ffa630}.td-box--2 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ffa630 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--2 p>a{color:#abc7f0}.td-box--12.td-box--gradient{background:#FFA630 -webkit-gradient(linear,left top,left bottom,from(#ffb34f),to(#FFA630)) repeat-x!important;background:#ffa630 -webkit-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 -o-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 linear-gradient(180deg,#ffb34f,#FFA630) repeat-x!important}.td-box--3{color:#222;background-color:#c0e0de}.td-box--3 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#c0e0de transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--3 p>a{color:#638ac1}.td-box--13.td-box--gradient{background:#C0E0DE -webkit-gradient(linear,left top,left bottom,from(#c9e5e3),to(#C0E0DE)) repeat-x!important;background:#c0e0de -webkit-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de -o-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de linear-gradient(180deg,#c9e5e3,#C0E0DE) repeat-x!important}.td-box--4{color:#222;background-color:#fff}.td-box--4 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#fff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--4 p>a{color:#72a1e5}.td-box--14.td-box--gradient{background:white -webkit-gradient(linear,left top,left bottom,from(white),to(white)) repeat-x!important;background:#fff -webkit-linear-gradient(top,white,white) repeat-x!important;background:#fff -o-linear-gradient(top,white,white) repeat-x!important;background:#fff linear-gradient(180deg,white,white) repeat-x!important}.td-box--5{color:#fff;background-color:#888}.td-box--5 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#888 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--5 p>a{color:#b4cdf1}.td-box--15.td-box--gradient{background:#888 -webkit-gradient(linear,left top,left bottom,from(#9a9a9a),to(#888)) repeat-x!important;background:#888 -webkit-linear-gradient(top,#9a9a9a,#888) repeat-x!important;background:#888 -o-linear-gradient(top,#9a9a9a,#888) repeat-x!important;background:#888 linear-gradient(180deg,#9a9a9a,#888) repeat-x!important}.td-box--6{color:#fff;background-color:#3772ff}.td-box--6 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#3772ff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--6 p>a{color:#a9c6ef}.td-box--16.td-box--gradient{background:#3772FF -webkit-gradient(linear,left top,left bottom,from(#5587ff),to(#3772FF)) repeat-x!important;background:#3772ff -webkit-linear-gradient(top,#5587ff,#3772FF) repeat-x!important;background:#3772ff -o-linear-gradient(top,#5587ff,#3772FF) repeat-x!important;background:#3772ff linear-gradient(180deg,#5587ff,#3772FF) repeat-x!important}.td-box--7{color:#fff;background-color:#ed6a5a}.td-box--7 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ed6a5a transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--7 p>a{color:#a5c3ee}.td-box--17.td-box--gradient{background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x!important;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x!important}.td-box--8{color:#fff;background-color:#403f4c}.td-box--8 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#403f4c transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--8 p>a{color:#d9e5f8}.td-box--18.td-box--gradient{background:#403F4C -webkit-gradient(linear,left top,left bottom,from(#5d5c67),to(#403F4C)) repeat-x!important;background:#403f4c -webkit-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c -o-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c linear-gradient(180deg,#5d5c67,#403F4C) repeat-x!important}.td-box--9{color:#fff;background-color:#ed6a5a}.td-box--9 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ed6a5a transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--9 p>a{color:#a5c3ee}.td-box--19.td-box--gradient{background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x!important;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x!important}.td-box--10{color:#fff;background-color:#30638e}.td-box--10 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#30638e transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--10 p>a{color:#cadcf5}.td-box--110.td-box--gradient{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x!important;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x!important}.td-box--11{color:#fff;background-color:#ffa630}.td-box--11 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ffa630 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--11 p>a{color:#abc7f0}.td-box--111.td-box--gradient{background:#FFA630 -webkit-gradient(linear,left top,left bottom,from(#ffb34f),to(#FFA630)) repeat-x!important;background:#ffa630 -webkit-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 -o-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 linear-gradient(180deg,#ffb34f,#FFA630) repeat-x!important}.td-box--12{color:#222;background-color:#fff}.td-box--12 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#fff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--12 p>a{color:#72a1e5}.td-box--112.td-box--gradient{background:white -webkit-gradient(linear,left top,left bottom,from(white),to(white)) repeat-x!important;background:#fff -webkit-linear-gradient(top,white,white) repeat-x!important;background:#fff -o-linear-gradient(top,white,white) repeat-x!important;background:#fff linear-gradient(180deg,white,white) repeat-x!important}.td-box--13{color:#222;background-color:#c0e0de}.td-box--13 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#c0e0de transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--13 p>a{color:#638ac1}.td-box--113.td-box--gradient{background:#C0E0DE -webkit-gradient(linear,left top,left bottom,from(#c9e5e3),to(#C0E0DE)) repeat-x!important;background:#c0e0de -webkit-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de -o-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de linear-gradient(180deg,#c9e5e3,#C0E0DE) repeat-x!important}.td-box--cerulean-blue{color:#fff;background-color:#017cee}.td-box--cerulean-blue .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#017cee transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--cerulean-blue p>a{color:#bdd3f3}.td-box--1cerulean-blue.td-box--gradient{background:#017cee -webkit-gradient(linear,left top,left bottom,from(#2790f1),to(#017cee)) repeat-x!important;background:#017cee -webkit-linear-gradient(top,#2790f1,#017cee) repeat-x!important;background:#017cee -o-linear-gradient(top,#2790f1,#017cee) repeat-x!important;background:#017cee linear-gradient(180deg,#2790f1,#017cee) repeat-x!important}.td-box--shamrock{color:#fff;background-color:#00ad46}.td-box--shamrock .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#00ad46 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--shamrock p>a{color:#cfdff6}.td-box--1shamrock.td-box--gradient{background:#00ad46 -webkit-gradient(linear,left top,left bottom,from(#26b962),to(#00ad46)) repeat-x!important;background:#00ad46 -webkit-linear-gradient(top,#26b962,#00ad46) repeat-x!important;background:#00ad46 -o-linear-gradient(top,#26b962,#00ad46) repeat-x!important;background:#00ad46 linear-gradient(180deg,#26b962,#00ad46) repeat-x!important}.td-box--bright-sky-blue{color:#fff;background-color:#0cb6ff}.td-box--bright-sky-blue .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#0cb6ff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--bright-sky-blue p>a{color:#b5cef1}.td-box--1bright-sky-blue.td-box--gradient{background:#0cb6ff -webkit-gradient(linear,left top,left bottom,from(#30c1ff),to(#0cb6ff)) repeat-x!important;background:#0cb6ff -webkit-linear-gradient(top,#30c1ff,#0cb6ff) repeat-x!important;background:#0cb6ff -o-linear-gradient(top,#30c1ff,#0cb6ff) repeat-x!important;background:#0cb6ff linear-gradient(180deg,#30c1ff,#0cb6ff) repeat-x!important}.td-box--melon{color:#fff;background-color:#ff7557}.td-box--melon .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ff7557 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--melon p>a{color:#a0c0ee}.td-box--1melon.td-box--gradient{background:#ff7557 -webkit-gradient(linear,left top,left bottom,from(#ff8a70),to(#ff7557)) repeat-x!important;background:#ff7557 -webkit-linear-gradient(top,#ff8a70,#ff7557) repeat-x!important;background:#ff7557 -o-linear-gradient(top,#ff8a70,#ff7557) repeat-x!important;background:#ff7557 linear-gradient(180deg,#ff8a70,#ff7557) repeat-x!important}.td-box--vermillion{color:#fff;background-color:#e43921}.td-box--vermillion .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#e43921 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--vermillion p>a{color:#b7cff2}.td-box--1vermillion.td-box--gradient{background:#e43921 -webkit-gradient(linear,left top,left bottom,from(#e85742),to(#e43921)) repeat-x!important;background:#e43921 -webkit-linear-gradient(top,#e85742,#e43921) repeat-x!important;background:#e43921 -o-linear-gradient(top,#e85742,#e43921) repeat-x!important;background:#e43921 linear-gradient(180deg,#e85742,#e43921) repeat-x!important}.td-box--aqua{color:#fff;background-color:#11e1ee}.td-box--aqua .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#11e1ee transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--aqua p>a{color:#b9d0f2}.td-box--1aqua.td-box--gradient{background:#11e1ee -webkit-gradient(linear,left top,left bottom,from(#35e6f1),to(#11e1ee)) repeat-x!important;background:#11e1ee -webkit-linear-gradient(top,#35e6f1,#11e1ee) repeat-x!important;background:#11e1ee -o-linear-gradient(top,#35e6f1,#11e1ee) repeat-x!important;background:#11e1ee linear-gradient(180deg,#35e6f1,#11e1ee) repeat-x!important}.td-box--shamrock-green{color:#fff;background-color:#04d659}.td-box--shamrock-green .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#04d659 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--shamrock-green p>a{color:#c3d7f4}.td-box--1shamrock-green.td-box--gradient{background:#04d659 -webkit-gradient(linear,left top,left bottom,from(#2adc72),to(#04d659)) repeat-x!important;background:#04d659 -webkit-linear-gradient(top,#2adc72,#04d659) repeat-x!important;background:#04d659 -o-linear-gradient(top,#2adc72,#04d659) repeat-x!important;background:#04d659 linear-gradient(180deg,#2adc72,#04d659) repeat-x!important}.td-box--aqua-blue{color:#fff;background-color:#00c7d4}.td-box--aqua-blue .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#00c7d4 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--aqua-blue p>a{color:#c4d8f4}.td-box--1aqua-blue.td-box--gradient{background:#00c7d4 -webkit-gradient(linear,left top,left bottom,from(#26cfda),to(#00c7d4)) repeat-x!important;background:#00c7d4 -webkit-linear-gradient(top,#26cfda,#00c7d4) repeat-x!important;background:#00c7d4 -o-linear-gradient(top,#26cfda,#00c7d4) repeat-x!important;background:#00c7d4 linear-gradient(180deg,#26cfda,#00c7d4) repeat-x!important}.td-box--white{color:#222;background-color:#fff}.td-box--white .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#fff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--white p>a{color:#72a1e5}.td-box--1white.td-box--gradient{background:#ffffff -webkit-gradient(linear,left top,left bottom,from(white),to(#ffffff)) repeat-x!important;background:#fff -webkit-linear-gradient(top,white,#ffffff) repeat-x!important;background:#fff -o-linear-gradient(top,white,#ffffff) repeat-x!important;background:#fff linear-gradient(180deg,white,#ffffff) repeat-x!important}.td-box--brownish-grey{color:#fff;background-color:#707070}.td-box--brownish-grey .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#707070 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--brownish-grey p>a{color:#c1d6f4}.td-box--1brownish-grey.td-box--gradient{background:#707070 -webkit-gradient(linear,left top,left bottom,from(#858585),to(#707070)) repeat-x!important;background:#707070 -webkit-linear-gradient(top,#858585,#707070) repeat-x!important;background:#707070 -o-linear-gradient(top,#858585,#707070) repeat-x!important;background:#707070 linear-gradient(180deg,#858585,#707070) repeat-x!important}.td-box--very-light-pink{color:#222;background-color:#cbcbcb}.td-box--very-light-pink .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#cbcbcb transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--very-light-pink p>a{color:#6287bd}.td-box--1very-light-pink.td-box--gradient{background:#cbcbcb -webkit-gradient(linear,left top,left bottom,from(lightgray),to(#cbcbcb)) repeat-x!important;background:#cbcbcb -webkit-linear-gradient(top,lightgray,#cbcbcb) repeat-x!important;background:#cbcbcb -o-linear-gradient(top,lightgray,#cbcbcb) repeat-x!important;background:#cbcbcb linear-gradient(180deg,lightgray,#cbcbcb) repeat-x!important}.td-box--slate-grey{color:#fff;background-color:#636365}.td-box--slate-grey .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#636365 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--slate-grey p>a{color:#c8daf5}.td-box--1slate-grey.td-box--gradient{background:#636365 -webkit-gradient(linear,left top,left bottom,from(#7a7a7c),to(#636365)) repeat-x!important;background:#636365 -webkit-linear-gradient(top,#7a7a7c,#636365) repeat-x!important;background:#636365 -o-linear-gradient(top,#7a7a7c,#636365) repeat-x!important;background:#636365 linear-gradient(180deg,#7a7a7c,#636365) repeat-x!important}.td-box--greyish-brown{color:#fff;background-color:#51504f}.td-box--greyish-brown .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#51504f transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--greyish-brown p>a{color:#d3e2f7}.td-box--1greyish-brown.td-box--gradient{background:#51504f -webkit-gradient(linear,left top,left bottom,from(#6b6a69),to(#51504f)) repeat-x!important;background:#51504f -webkit-linear-gradient(top,#6b6a69,#51504f) repeat-x!important;background:#51504f -o-linear-gradient(top,#6b6a69,#51504f) repeat-x!important;background:#51504f linear-gradient(180deg,#6b6a69,#51504f) repeat-x!important}.td-box--primary{color:#fff;background-color:#30638e}.td-box--primary .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#30638e transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--primary p>a{color:#cadcf5}.td-box--1primary.td-box--gradient{background:#30638E -webkit-gradient(linear,left top,left bottom,from(#4f7a9f),to(#30638E)) repeat-x!important;background:#30638e -webkit-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e -o-linear-gradient(top,#4f7a9f,#30638E) repeat-x!important;background:#30638e linear-gradient(180deg,#4f7a9f,#30638E) repeat-x!important}.td-box--secondary{color:#fff;background-color:#ffa630}.td-box--secondary .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ffa630 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--secondary p>a{color:#abc7f0}.td-box--1secondary.td-box--gradient{background:#FFA630 -webkit-gradient(linear,left top,left bottom,from(#ffb34f),to(#FFA630)) repeat-x!important;background:#ffa630 -webkit-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 -o-linear-gradient(top,#ffb34f,#FFA630) repeat-x!important;background:#ffa630 linear-gradient(180deg,#ffb34f,#FFA630) repeat-x!important}.td-box--success{color:#fff;background-color:#3772ff}.td-box--success .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#3772ff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--success p>a{color:#a9c6ef}.td-box--1success.td-box--gradient{background:#3772FF -webkit-gradient(linear,left top,left bottom,from(#5587ff),to(#3772FF)) repeat-x!important;background:#3772ff -webkit-linear-gradient(top,#5587ff,#3772FF) repeat-x!important;background:#3772ff -o-linear-gradient(top,#5587ff,#3772FF) repeat-x!important;background:#3772ff linear-gradient(180deg,#5587ff,#3772FF) repeat-x!important}.td-box--info{color:#222;background-color:#c0e0de}.td-box--info .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#c0e0de transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--info p>a{color:#638ac1}.td-box--1info.td-box--gradient{background:#C0E0DE -webkit-gradient(linear,left top,left bottom,from(#c9e5e3),to(#C0E0DE)) repeat-x!important;background:#c0e0de -webkit-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de -o-linear-gradient(top,#c9e5e3,#C0E0DE) repeat-x!important;background:#c0e0de linear-gradient(180deg,#c9e5e3,#C0E0DE) repeat-x!important}.td-box--warning{color:#fff;background-color:#ed6a5a}.td-box--warning .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ed6a5a transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--warning p>a{color:#a5c3ee}.td-box--1warning.td-box--gradient{background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x!important;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x!important}.td-box--danger{color:#fff;background-color:#ed6a5a}.td-box--danger .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ed6a5a transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--danger p>a{color:#a5c3ee}.td-box--1danger.td-box--gradient{background:#ED6A5A -webkit-gradient(linear,left top,left bottom,from(#f08073),to(#ED6A5A)) repeat-x!important;background:#ed6a5a -webkit-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a -o-linear-gradient(top,#f08073,#ED6A5A) repeat-x!important;background:#ed6a5a linear-gradient(180deg,#f08073,#ED6A5A) repeat-x!important}.td-box--light{color:#222;background-color:#d3f3ee}.td-box--light .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#d3f3ee transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--light p>a{color:#6993d0}.td-box--1light.td-box--gradient{background:#D3F3EE -webkit-gradient(linear,left top,left bottom,from(#daf5f1),to(#D3F3EE)) repeat-x!important;background:#d3f3ee -webkit-linear-gradient(top,#daf5f1,#D3F3EE) repeat-x!important;background:#d3f3ee -o-linear-gradient(top,#daf5f1,#D3F3EE) repeat-x!important;background:#d3f3ee linear-gradient(180deg,#daf5f1,#D3F3EE) repeat-x!important}.td-box--dark{color:#fff;background-color:#403f4c}.td-box--dark .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#403f4c transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--dark p>a{color:#d9e5f8}.td-box--1dark.td-box--gradient{background:#403F4C -webkit-gradient(linear,left top,left bottom,from(#5d5c67),to(#403F4C)) repeat-x!important;background:#403f4c -webkit-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c -o-linear-gradient(top,#5d5c67,#403F4C) repeat-x!important;background:#403f4c linear-gradient(180deg,#5d5c67,#403F4C) repeat-x!important}.td-box--100{color:#222;background-color:#f8f9fa}.td-box--100 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#f8f9fa transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--100 p>a{color:#709ee0}.td-box--1100.td-box--gradient{background:#f8f9fa -webkit-gradient(linear,left top,left bottom,from(#f9fafb),to(#f8f9fa)) repeat-x!important;background:#f8f9fa -webkit-linear-gradient(top,#f9fafb,#f8f9fa) repeat-x!important;background:#f8f9fa -o-linear-gradient(top,#f9fafb,#f8f9fa) repeat-x!important;background:#f8f9fa linear-gradient(180deg,#f9fafb,#f8f9fa) repeat-x!important}.td-box--200{color:#222;background-color:#eee}.td-box--200 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#eee transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--200 p>a{color:#6d99d8}.td-box--1200.td-box--gradient{background:#eee -webkit-gradient(linear,left top,left bottom,from(#f1f1f1),to(#eee)) repeat-x!important;background:#eee -webkit-linear-gradient(top,#f1f1f1,#eee) repeat-x!important;background:#eee -o-linear-gradient(top,#f1f1f1,#eee) repeat-x!important;background:#eee linear-gradient(180deg,#f1f1f1,#eee) repeat-x!important}.td-box--300{color:#222;background-color:#dee2e6}.td-box--300 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#dee2e6 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--300 p>a{color:#6993cf}.td-box--1300.td-box--gradient{background:#dee2e6 -webkit-gradient(linear,left top,left bottom,from(#e3e6ea),to(#dee2e6)) repeat-x!important;background:#dee2e6 -webkit-linear-gradient(top,#e3e6ea,#dee2e6) repeat-x!important;background:#dee2e6 -o-linear-gradient(top,#e3e6ea,#dee2e6) repeat-x!important;background:#dee2e6 linear-gradient(180deg,#e3e6ea,#dee2e6) repeat-x!important}.td-box--400{color:#222;background-color:#ccc}.td-box--400 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ccc transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--400 p>a{color:#6288be}.td-box--1400.td-box--gradient{background:#ccc -webkit-gradient(linear,left top,left bottom,from(#d4d4d4),to(#ccc)) repeat-x!important;background:#ccc -webkit-linear-gradient(top,#d4d4d4,#ccc) repeat-x!important;background:#ccc -o-linear-gradient(top,#d4d4d4,#ccc) repeat-x!important;background:#ccc linear-gradient(180deg,#d4d4d4,#ccc) repeat-x!important}.td-box--500{color:#fff;background-color:#adb5bd}.td-box--500 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#adb5bd transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--500 p>a{color:#9bbced}.td-box--1500.td-box--gradient{background:#adb5bd -webkit-gradient(linear,left top,left bottom,from(#b9c0c7),to(#adb5bd)) repeat-x!important;background:#adb5bd -webkit-linear-gradient(top,#b9c0c7,#adb5bd) repeat-x!important;background:#adb5bd -o-linear-gradient(top,#b9c0c7,#adb5bd) repeat-x!important;background:#adb5bd linear-gradient(180deg,#b9c0c7,#adb5bd) repeat-x!important}.td-box--600{color:#fff;background-color:#888}.td-box--600 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#888 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--600 p>a{color:#b4cdf1}.td-box--1600.td-box--gradient{background:#888 -webkit-gradient(linear,left top,left bottom,from(#9a9a9a),to(#888)) repeat-x!important;background:#888 -webkit-linear-gradient(top,#9a9a9a,#888) repeat-x!important;background:#888 -o-linear-gradient(top,#9a9a9a,#888) repeat-x!important;background:#888 linear-gradient(180deg,#9a9a9a,#888) repeat-x!important}.td-box--700{color:#fff;background-color:#495057}.td-box--700 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#495057 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--700 p>a{color:#d3e2f7}.td-box--1700.td-box--gradient{background:#495057 -webkit-gradient(linear,left top,left bottom,from(#646a70),to(#495057)) repeat-x!important;background:#495057 -webkit-linear-gradient(top,#646a70,#495057) repeat-x!important;background:#495057 -o-linear-gradient(top,#646a70,#495057) repeat-x!important;background:#495057 linear-gradient(180deg,#646a70,#495057) repeat-x!important}.td-box--800{color:#fff;background-color:#333}.td-box--800 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#333 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--800 p>a{color:#e3ecfa}.td-box--1800.td-box--gradient{background:#333 -webkit-gradient(linear,left top,left bottom,from(#525252),to(#333)) repeat-x!important;background:#333 -webkit-linear-gradient(top,#525252,#333) repeat-x!important;background:#333 -o-linear-gradient(top,#525252,#333) repeat-x!important;background:#333 linear-gradient(180deg,#525252,#333) repeat-x!important}.td-box--900{color:#fff;background-color:#222}.td-box--900 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#222 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--900 p>a{color:#ecf2fc}.td-box--1900.td-box--gradient{background:#222 -webkit-gradient(linear,left top,left bottom,from(#434343),to(#222)) repeat-x!important;background:#222 -webkit-linear-gradient(top,#434343,#222) repeat-x!important;background:#222 -o-linear-gradient(top,#434343,#222) repeat-x!important;background:#222 linear-gradient(180deg,#434343,#222) repeat-x!important}.td-blog .td-rss-button{position:absolute;top:5.5rem;right:1rem;z-index:22}.td-content .highlight{margin:2rem 0;padding:1rem;background-color:#f8f9fa}.td-content .highlight pre,.td-content .highlight div{background-color:inherit!important}.td-content .highlight pre{margin:0;padding:0}.td-content p code,.td-content li>code,.td-content table code{color:inherit;padding:.2em .4em;margin:0;font-size:85%;word-break:normal;background-color:rgba(0,0,0,.05);border-radius:.25rem}.td-content p code br,.td-content li>code br,.td-content table code br{display:none}.td-content pre{word-wrap:normal;background-color:#f8f9fa;padding:1rem}.td-content pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;border:0}.td-navbar-cover{background:#30638e}@media(min-width:768px){.td-navbar-cover{background:transparent!important}.td-navbar-cover .nav-link{text-shadow:1px 1px 2px #403f4c}}.td-navbar-cover.navbar-bg-onscroll .nav-link{text-shadow:none}.navbar-bg-onscroll{background:#30638e!important;opacity:inherit}.td-navbar{background:#30638e;min-height:4rem;margin:0;z-index:32}@media(min-width:768px){.td-navbar{position:fixed;top:0;width:100%}}.td-navbar .navbar-brand{text-transform:none;text-align:middle}.td-navbar .navbar-brand .nav-link{display:inline-block;margin-right:-30px}.td-navbar .navbar-brand svg{display:inline-block;margin:0 10px;height:30px}.td-navbar .nav-link{text-transform:none;font-weight:700}.td-navbar .td-search-input{border:none}.td-navbar .td-search-input::-webkit-input-placeholder{color:rgba(255,255,255,.75)}.td-navbar .td-search-input:-moz-placeholder{color:rgba(255,255,255,.75)}.td-navbar .td-search-input::-moz-placeholder{color:rgba(255,255,255,.75)}.td-navbar .td-search-input:-ms-input-placeholder{color:rgba(255,255,255,.75)}.td-navbar .dropdown{min-width:100px}@media(max-width:991.98px){.td-navbar{padding-right:.5rem;padding-left:.75rem}.td-navbar .td-navbar-nav-scroll{max-width:100%;height:2.5rem;margin-top:.25rem;overflow:hidden;font-size:.875rem}.td-navbar .td-navbar-nav-scroll .nav-link{padding-right:.25rem;padding-left:0}.td-navbar .td-navbar-nav-scroll .navbar-nav{padding-bottom:2rem;overflow-x:auto;white-space:nowrap;-webkit-overflow-scrolling:touch}}.td-sidebar-nav{padding-right:.5rem;margin-right:-15px;margin-left:-15px}@media(min-width:768px){@supports((position:-webkit-sticky) or (position:sticky)){.td-sidebar-nav{max-height:-webkit-calc(100vh - 10rem);max-height:calc(100vh - 10rem);overflow-y:auto}}}@media(min-width:768px){.td-sidebar-nav{display:block!important}}.td-sidebar-nav__section{padding-left:0}.td-sidebar-nav__section li{list-style:none}.td-sidebar-nav__section ul{padding:0;margin:0}@media(min-width:768px){.td-sidebar-nav__section>ul{padding-left:.5rem}}.td-sidebar-nav__section-title{display:block;font-weight:500}.td-sidebar-nav__section-title .active{font-weight:700}.td-sidebar-nav__section-title a{color:#222}.td-sidebar-nav .td-sidebar-link{display:block;padding-bottom:.375rem}.td-sidebar-nav .td-sidebar-link__page{color:#495057;font-weight:300}.td-sidebar-nav a:hover{color:#72a1e5;text-decoration:none}.td-sidebar-nav a.active{font-weight:700}.td-sidebar-nav .dropdown a{color:#495057}.td-sidebar-nav .dropdown .nav-link{padding:0 0 1rem}.td-sidebar{padding-bottom:1rem}@media(min-width:768px){.td-sidebar{padding-top:4rem;background-color:rgba(48,99,142,.03);padding-right:1rem;border-right:1px solid #dee2e6}}.td-sidebar__toggle{line-height:1;color:#222;margin:1rem}.td-sidebar__search{padding:1rem 15px;margin-right:-15px;margin-left:-15px}.td-sidebar__inner{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}@media(min-width:768px){@supports((position:-webkit-sticky) or (position:sticky)){.td-sidebar__inner{position:-webkit-sticky;position:sticky;top:4rem;z-index:10;height:-webkit-calc(100vh - 6rem);height:calc(100vh - 6rem)}}}@media(min-width:1200px){.td-sidebar__inner{-webkit-box-flex:0;-webkit-flex:0 1 320px;-ms-flex:0 1 320px;flex:0 1 320px}}.td-sidebar__inner .td-search-box{width:100%}.td-toc{border-left:1px solid #dee2e6;-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2;padding-top:.75rem;padding-bottom:1.5rem;vertical-align:top}@supports((position:-webkit-sticky) or (position:sticky)){.td-toc{position:-webkit-sticky;position:sticky;top:4rem;height:-webkit-calc(100vh - 10rem);height:calc(100vh - 10rem);overflow-y:auto}}.td-toc a{display:block;font-weight:300;padding-bottom:.25rem}.td-toc li{list-style:none;display:block}.td-toc li li{margin-left:.5rem}.td-toc .td-page-meta a{font-weight:500}.td-toc #TableOfContents a{color:#888}.td-toc #TableOfContents a:hover{color:#72a1e5;text-decoration:none}.td-toc ul{padding-left:0}button{cursor:pointer;border:1px solid;border-radius:5px;padding:9px 29px;-webkit-transition:all ease-out .2s;-o-transition:all ease-out .2s;transition:all ease-out .2s}button:disabled{cursor:not-allowed}button.btn-filled{border-color:#017cee;background-color:#017cee}button.btn-filled:hover{border-color:#0cb6ff;background-color:#0cb6ff}button.btn-with-icon{padding:14px 20px}button.btn-with-icon svg{height:30px;width:auto;padding-right:15px}button.btn-with-icon span{display:inline-block;line-height:30px;vertical-align:middle}button.btn-hollow{background-color:#fff}button.btn-hollow.btn-blue{color:#017cee;border-color:#017cee}button.btn-hollow.btn-blue:disabled{color:#cbcbcb;border-color:#cbcbcb}button.btn-hollow.btn-blue:hover:enabled{color:#fff;background-color:#017cee}button.btn-hollow.btn-brown{border-color:#cbcbcb}button.btn-hollow.btn-brown:hover{background-color:#51504f;border-color:#51504f}button.btn-hollow.btn-brown:hover span{color:#fff}button.btn-hollow.btn-brown:hover svg path{fill:#fff}button.with-box-shadow{-webkit-box-shadow:0 2px 6px 0 rgba(0,0,0,.12);box-shadow:0 2px 6px 0 rgba(0,0,0,.12)}@media(max-width:1280px){button{padding:4px 17px}}.breadcrumb{background:0 0;padding-left:0;padding-top:0}.alert{font-weight:500;background:#fff;color:inherit;border-radius:0}.alert-primary{border-style:solid;border-color:#30638e;border-width:0 0 0 4px}.alert-primary .alert-heading{color:#30638e}.alert-secondary{border-style:solid;border-color:#ffa630;border-width:0 0 0 4px}.alert-secondary .alert-heading{color:#ffa630}.alert-success{border-style:solid;border-color:#3772ff;border-width:0 0 0 4px}.alert-success .alert-heading{color:#3772ff}.alert-info{border-style:solid;border-color:#c0e0de;border-width:0 0 0 4px}.alert-info .alert-heading{color:#c0e0de}.alert-warning{border-style:solid;border-color:#ed6a5a;border-width:0 0 0 4px}.alert-warning .alert-heading{color:#ed6a5a}.alert-danger{border-style:solid;border-color:#ed6a5a;border-width:0 0 0 4px}.alert-danger .alert-heading{color:#ed6a5a}.alert-light{border-style:solid;border-color:#d3f3ee;border-width:0 0 0 4px}.alert-light .alert-heading{color:#d3f3ee}.alert-dark{border-style:solid;border-color:#403f4c;border-width:0 0 0 4px}.alert-dark .alert-heading{color:#403f4c}.td-content{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.td-content p,.td-content li,.td-content td{font-weight:400}.td-content>h1{font-weight:700;margin-bottom:1rem}.td-content>h2{margin-bottom:1rem}.td-content>h2:not(:first-child){margin-top:3rem}.td-content>h2+h3{margin-top:1rem}.td-content>h3,.td-content>h4,.td-content>h5,.td-content>h6{margin-bottom:1rem;margin-top:2rem}.td-content>blockquote{padding:0 0 0 1rem;margin-bottom:1rem;color:#888;border-left:6px solid #ffa630}.td-content>ul li,.td-content>ol li{margin-bottom:.25rem}.td-content strong{font-weight:700}.td-content .alert:not(:first-child){margin-top:2rem;margin-bottom:2rem}.td-content .lead{margin-bottom:1.5rem}.td-title{margin-top:1rem;margin-bottom:.5rem}@media(min-width:576px){.td-title{font-size:3rem}}.search-form{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:344px;padding:8px 20px;border:solid 1px #cbcbcb;border-radius:5px;margin:60px auto 0}.search-form__input{font-family:roboto,sans-serif;font-size:16px;color:#707070;line-height:1.63;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;padding-right:10px;border:none;background:0 0;outline:none;float:left}.search-form__button{border:none;background-color:transparent;padding:0}@media(max-width:1280px){.search-form{width:270px;padding:3px 20px;margin-top:30px}}.td-outer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;height:100vh}@media(min-width:768px){.td-default main section:first-of-type{padding-top:8rem}}.td-main{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1}.td-main main{padding-bottom:2rem}@media(min-width:768px){.td-main main{padding-top:5.5rem}}.td-cover-block--height-min{min-height:300px}.td-cover-block--height-med{min-height:400px}.td-cover-block--height-max{min-height:500px}.td-cover-block--height-full{min-height:100vh}@media(min-width:768px){.td-cover-block--height-min{min-height:450px}.td-cover-block--height-med{min-height:500px}.td-cover-block--height-max{min-height:650px}}.td-cover-logo{margin-right:.5em}.td-cover-block{position:relative;padding-top:5rem;padding-bottom:5rem;background-repeat:no-repeat;background-position:50% 0;-webkit-background-size:cover;background-size:cover}.td-bg-arrow-wrapper{position:relative}.section-index .entry{padding:.75rem}.section-index h5{margin-bottom:0}.section-index h5 a{font-weight:700}.section-index p{margin-top:0}.pageinfo{font-weight:500;background:#f8f9fa;color:inherit;border-radius:0;margin:2rem;padding:1.5rem;padding-bottom:.5rem}.pageinfo-primary{border-style:solid;border-color:#30638e}.pageinfo-secondary{border-style:solid;border-color:#ffa630}.pageinfo-success{border-style:solid;border-color:#3772ff}.pageinfo-info{border-style:solid;border-color:#c0e0de}.pageinfo-warning{border-style:solid;border-color:#ed6a5a}.pageinfo-danger{border-style:solid;border-color:#ed6a5a}.pageinfo-light{border-style:solid;border-color:#d3f3ee}.pageinfo-dark{border-style:solid;border-color:#403f4c}footer{min-height:150px}@media(max-width:991.98px){footer{min-height:200px}}@media(min-width:768px){.td-offset-anchor:target{display:block;position:relative;top:-4rem;visibility:hidden}h2[id]:before,h3[id]:before,h4[id]:before,h5[id]:before{display:block;content:" ";margin-top:-5rem;height:5rem;visibility:hidden}} \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_static/_gen/js/docs.js b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/_gen/js/docs.js new file mode 100644 index 00000000000..90898d86d50 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/_gen/js/docs.js @@ -0,0 +1 @@ +!function(r){var n={};function o(t){if(n[t])return n[t].exports;var e=n[t]={i:t,l:!1,exports:{}};return r[t].call(e.exports,e,e.exports,o),e.l=!0,e.exports}o.m=r,o.c=n,o.d=function(t,e,r){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(o.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)o.d(r,n,function(t){return e[t]}.bind(null,n));return r},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o.p="/",o(o.s=54)}([function(t,e,r){var m=r(1),w=r(14),g=r(15),E=Math.max,x=Math.min;t.exports=function(n,r,t){var o,i,a,s,u,c,f=0,l=!1,d=!1,e=!0;if("function"!=typeof n)throw new TypeError("Expected a function");function h(t){var e=o,r=i;return o=i=void 0,f=t,s=n.apply(r,e)}function p(t){var e=t-c;return void 0===c||r<=e||e<0||d&&a<=t-f}function y(){var t=w();if(p(t))return b(t);u=setTimeout(y,function(t){var e=r-(t-c);return d?x(e,a-(t-f)):e}(t))}function b(t){return u=void 0,e&&o?h(t):(o=i=void 0,s)}function v(){var t=w(),e=p(t);if(o=arguments,i=this,c=t,e){if(void 0===u)return function(t){return f=t,u=setTimeout(y,r),l?h(t):s}(c);if(d)return clearTimeout(u),u=setTimeout(y,r),h(c)}return void 0===u&&(u=setTimeout(y,r)),s}return r=g(r)||0,m(t)&&(l=!!t.leading,a=(d="maxWait"in t)?E(g(t.maxWait)||0,r):a,e="trailing"in t?!!t.trailing:e),v.cancel=function(){void 0!==u&&clearTimeout(u),o=c=i=u=void(f=0)},v.flush=function(){return void 0===u?s:b(w())},v}},function(t,e){t.exports=function(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}},function(t,e,r){var n=r(8),o="object"==typeof self&&self&&self.Object===Object&&self,i=n||o||Function("return this")();t.exports=i},function(t,e,r){var n=r(6),o=r(17),i=r(18),a=n?n.toStringTag:void 0;t.exports=function(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":a&&a in Object(t)?o(t):i(t)}},function(t,e){t.exports=function(t){return null!=t&&"object"==typeof t}},function(t,e,r){!function(s){"use strict";var u={searchParams:"URLSearchParams"in self,iterable:"Symbol"in self&&"iterator"in Symbol,blob:"FileReader"in self&&"Blob"in self&&function(){try{return new Blob,!0}catch(t){return!1}}(),formData:"FormData"in self,arrayBuffer:"ArrayBuffer"in self};if(u.arrayBuffer)var e=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],r=ArrayBuffer.isView||function(t){return t&&-1 nav").offsetHeight,n=function(){var t;e.sort(function(t,e){return t.targetElement.offsetTop-e.targetElement.offsetTop}),t=e[0].targetElement.offsetTop+r>window.scrollY?0:e[e.length-1].targetElement.offsetTop+rwindow.scrollY})-1,e.forEach(function(t){return t.navElement.classList.remove("current")}),e[t].navElement.classList.add("current")};window.addEventListener("scroll",o()(n,10)),window.addEventListener("resize",o()(n,10)),n()}}()},function(t,e,r){var n=r(2);t.exports=function(){return n.Date.now()}},function(t,e,r){var n=r(1),o=r(16),i=/^\s+|\s+$/g,a=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,u=/^0o[0-7]+$/i,c=parseInt;t.exports=function(t){if("number"==typeof t)return t;if(o(t))return NaN;if(n(t)){var e="function"==typeof t.valueOf?t.valueOf():t;t=n(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=t.replace(i,"");var r=s.test(t);return r||u.test(t)?c(t.slice(2),r?2:8):a.test(t)?NaN:+t}},function(t,e,r){var n=r(3),o=r(4);t.exports=function(t){return"symbol"==typeof t||o(t)&&"[object Symbol]"==n(t)}},function(t,e,r){var n=r(6),o=Object.prototype,i=o.hasOwnProperty,a=o.toString,s=n?n.toStringTag:void 0;t.exports=function(t){var e=i.call(t,s),r=t[s];try{var n=!(t[s]=void 0)}catch(t){}var o=a.call(t);return n&&(e?t[s]=r:delete t[s]),o}},function(t,e){var r=Object.prototype.toString;t.exports=function(t){return r.call(t)}},function(t,e){!function(){var e=window.document.querySelector(".rating");if(e){function t(t){e.querySelector("#rate-star-".concat(t)).addEventListener("click",function(){!function(t){window._paq.push(["trackEvent","Docs","Rating",window.location.pathname,t])}(t),e.innerHTML="

Thank you!

"})}for(var r=1;r<=5;r++)t(r)}}()},function(t,e){var r=window.document.querySelector(".rst-content");!function(){if(r){var t=r.querySelectorAll("table");t&&0!==t.length&&t.forEach(function(t){if(!t.parentNode.classList.contains("wy-table-responsive")){var e=document.createElement("div");e.classList.add("wy-table-responsive"),t.parentNode.insertBefore(e,t),e.appendChild(t)}})}}()},function(t,e,n){"use strict";(function(t){var i=n(7);function r(t){return function(t){if(Array.isArray(t))return t}(t)||function(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}(t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function f(){var t=r(document.location.pathname.split("/")),e=t[2];return{currentVersion:t[3],currentPackageName:e,pagePath:t.slice(4).join("/")}}var a;(a=window.document.querySelectorAll(".docs-version-selector"))&&0!==a.length&&t("/_gen/packages-metadata.json").then(function(t){return t.json()}).then(function(t){var e=f().currentPackageName,r=t.find(function(t){return t["package-name"]===e});if(r){var n=r["all-versions"].sort(i.a).reverse(),o=r["stable-version"];a.forEach(function(t){return function(t,e,r){var n=t.querySelector("#version-item-template").innerText,o=document.createElement("div");function i(t,e){var r=o.cloneNode(!0),n="/docs/".concat(u,"/").concat(t,"/").concat(c);r.setAttribute("href",n),r.innerText=e,a.appendChild(r)}o.innerHTML=n,o=o.firstElementChild;var a=t.querySelector(".dropdown-menu"),s=f(),u=s.currentPackageName,c=s.pagePath;i("stable","Stable (".concat(r,")")),e.forEach(function(t){return i(t,t)})}(t,n,o)})}})}).call(this,n(5))},,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,function(t,e,r){"use strict";r.r(e);r(10),r(11),r(12),r(13),r(19),r(20),r(55),r(21)},function(t,e){Array.from(document.querySelectorAll(".toctree ul")).forEach(function(t){Array.from(t.parentNode.children).filter(function(t){return"A"===t.tagName}).forEach(function(t){var e=document.createElement("span");e.classList.add("toctree-expand"),t.insertBefore(e,t.firstChild)})})}]); \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_static/_sphinx_javascript_frameworks_compat.js b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/_sphinx_javascript_frameworks_compat.js new file mode 100644 index 00000000000..8549469dc29 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/_sphinx_javascript_frameworks_compat.js @@ -0,0 +1,134 @@ +/* + * _sphinx_javascript_frameworks_compat.js + * ~~~~~~~~~~ + * + * Compatability shim for jQuery and underscores.js. + * + * WILL BE REMOVED IN Sphinx 6.0 + * xref RemovedInSphinx60Warning + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_static/basic.css b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/basic.css new file mode 100644 index 00000000000..eeb0519a69b --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/basic.css @@ -0,0 +1,899 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} +dl.field-list > dt:after { + content: ":"; +} + + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_static/check-solid.svg b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/check-solid.svg new file mode 100644 index 00000000000..92fad4b5c0b --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/check-solid.svg @@ -0,0 +1,4 @@ + + + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_static/clipboard.min.js b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/clipboard.min.js new file mode 100644 index 00000000000..54b3c463811 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.8 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1 + + + + diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_static/copybutton.css b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/copybutton.css new file mode 100644 index 00000000000..f1916ec7d1b --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/copybutton.css @@ -0,0 +1,94 @@ +/* Copy buttons */ +button.copybtn { + position: absolute; + display: flex; + top: .3em; + right: .3em; + width: 1.7em; + height: 1.7em; + opacity: 0; + transition: opacity 0.3s, border .3s, background-color .3s; + user-select: none; + padding: 0; + border: none; + outline: none; + border-radius: 0.4em; + /* The colors that GitHub uses */ + border: #1b1f2426 1px solid; + background-color: #f6f8fa; + color: #57606a; +} + +button.copybtn.success { + border-color: #22863a; + color: #22863a; +} + +button.copybtn svg { + stroke: currentColor; + width: 1.5em; + height: 1.5em; + padding: 0.1em; +} + +div.highlight { + position: relative; +} + +/* Show the copybutton */ +.highlight:hover button.copybtn, button.copybtn.success { + opacity: 1; +} + +.highlight button.copybtn:hover { + background-color: rgb(235, 235, 235); +} + +.highlight button.copybtn:active { + background-color: rgb(187, 187, 187); +} + +/** + * A minimal CSS-only tooltip copied from: + * https://codepen.io/mildrenben/pen/rVBrpK + * + * To use, write HTML like the following: + * + *

Short

+ */ + .o-tooltip--left { + position: relative; + } + + .o-tooltip--left:after { + opacity: 0; + visibility: hidden; + position: absolute; + content: attr(data-tooltip); + padding: .2em; + font-size: .8em; + left: -.2em; + background: grey; + color: white; + white-space: nowrap; + z-index: 2; + border-radius: 2px; + transform: translateX(-102%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); +} + +.o-tooltip--left:hover:after { + display: block; + opacity: 1; + visibility: visible; + transform: translateX(-100%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); + transition-delay: .5s; +} + +/* By default the copy button shouldn't show up when printing a page */ +@media print { + button.copybtn { + display: none; + } +} diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_static/copybutton.js b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/copybutton.js new file mode 100644 index 00000000000..2ea7ff3e217 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/copybutton.js @@ -0,0 +1,248 @@ +// Localization support +const messages = { + 'en': { + 'copy': 'Copy', + 'copy_to_clipboard': 'Copy to clipboard', + 'copy_success': 'Copied!', + 'copy_failure': 'Failed to copy', + }, + 'es' : { + 'copy': 'Copiar', + 'copy_to_clipboard': 'Copiar al portapapeles', + 'copy_success': '¡Copiado!', + 'copy_failure': 'Error al copiar', + }, + 'de' : { + 'copy': 'Kopieren', + 'copy_to_clipboard': 'In die Zwischenablage kopieren', + 'copy_success': 'Kopiert!', + 'copy_failure': 'Fehler beim Kopieren', + }, + 'fr' : { + 'copy': 'Copier', + 'copy_to_clipboard': 'Copier dans le presse-papier', + 'copy_success': 'Copié !', + 'copy_failure': 'Échec de la copie', + }, + 'ru': { + 'copy': 'Скопировать', + 'copy_to_clipboard': 'Скопировать в буфер', + 'copy_success': 'Скопировано!', + 'copy_failure': 'Не удалось скопировать', + }, + 'zh-CN': { + 'copy': '复制', + 'copy_to_clipboard': '复制到剪贴板', + 'copy_success': '复制成功!', + 'copy_failure': '复制失败', + }, + 'it' : { + 'copy': 'Copiare', + 'copy_to_clipboard': 'Copiato negli appunti', + 'copy_success': 'Copiato!', + 'copy_failure': 'Errore durante la copia', + } +} + +let locale = 'en' +if( document.documentElement.lang !== undefined + && messages[document.documentElement.lang] !== undefined ) { + locale = document.documentElement.lang +} + +let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT; +if (doc_url_root == '#') { + doc_url_root = ''; +} + +/** + * SVG files for our copy buttons + */ +let iconCheck = ` + ${messages[locale]['copy_success']} + + +` + +// If the user specified their own SVG use that, otherwise use the default +let iconCopy = ``; +if (!iconCopy) { + iconCopy = ` + ${messages[locale]['copy_to_clipboard']} + + + +` +} + +/** + * Set up copy/paste for code blocks + */ + +const runWhenDOMLoaded = cb => { + if (document.readyState != 'loading') { + cb() + } else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', cb) + } else { + document.attachEvent('onreadystatechange', function() { + if (document.readyState == 'complete') cb() + }) + } +} + +const codeCellId = index => `codecell${index}` + +// Clears selected text since ClipboardJS will select the text when copying +const clearSelection = () => { + if (window.getSelection) { + window.getSelection().removeAllRanges() + } else if (document.selection) { + document.selection.empty() + } +} + +// Changes tooltip text for a moment, then changes it back +// We want the timeout of our `success` class to be a bit shorter than the +// tooltip and icon change, so that we can hide the icon before changing back. +var timeoutIcon = 2000; +var timeoutSuccessClass = 1500; + +const temporarilyChangeTooltip = (el, oldText, newText) => { + el.setAttribute('data-tooltip', newText) + el.classList.add('success') + // Remove success a little bit sooner than we change the tooltip + // So that we can use CSS to hide the copybutton first + setTimeout(() => el.classList.remove('success'), timeoutSuccessClass) + setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon) +} + +// Changes the copy button icon for two seconds, then changes it back +const temporarilyChangeIcon = (el) => { + el.innerHTML = iconCheck; + setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon) +} + +const addCopyButtonToCodeCells = () => { + // If ClipboardJS hasn't loaded, wait a bit and try again. This + // happens because we load ClipboardJS asynchronously. + if (window.ClipboardJS === undefined) { + setTimeout(addCopyButtonToCodeCells, 250) + return + } + + // Add copybuttons to all of our code cells + const COPYBUTTON_SELECTOR = 'div.highlight pre'; + const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR) + codeCells.forEach((codeCell, index) => { + const id = codeCellId(index) + codeCell.setAttribute('id', id) + + const clipboardButton = id => + `` + codeCell.insertAdjacentHTML('afterend', clipboardButton(id)) + }) + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} + + +var copyTargetText = (trigger) => { + var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); + + // get filtered text + let exclude = '.linenos'; + + let text = filterText(target, exclude); + return formatCopyText(text, '', false, true, true, true, '', '') +} + + // Initialize with a callback so we can modify the text before copy + const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText}) + + // Update UI with error/success messages + clipboard.on('success', event => { + clearSelection() + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success']) + temporarilyChangeIcon(event.trigger) + }) + + clipboard.on('error', event => { + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure']) + }) +} + +runWhenDOMLoaded(addCopyButtonToCodeCells) \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_static/copybutton_funcs.js b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/copybutton_funcs.js new file mode 100644 index 00000000000..dbe1aaad79c --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/copybutton_funcs.js @@ -0,0 +1,73 @@ +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +export function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_static/custom.css b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/custom.css new file mode 100644 index 00000000000..b1cf49f37d4 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/custom.css @@ -0,0 +1,33 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + /* + This file contains style overrides for the sphinx-design extension. + + The original defaults can be found here: + https://sphinx-design.readthedocs.io/en/alabaster-theme/css_variables.html + */ + +:root { + --sd-color-tabs-label-active: #017cee; + --sd-color-tabs-label-hover: #68d1ff; + --sd-color-tabs-underline-active: #017cee; + --sd-color-tabs-underline-hover: #68d1ff; + --sd-color-tabs-underline: transparent; +} diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css new file mode 100644 index 00000000000..eb19f698afc --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css @@ -0,0 +1 @@ +.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative}details.sd-dropdown .sd-summary-title{font-weight:700;padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary{list-style:none;padding:1em}details.sd-dropdown summary .sd-octicon.no-title{vertical-align:middle}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown summary::-webkit-details-marker{display:none}details.sd-dropdown summary:focus{outline:none}details.sd-dropdown .sd-summary-icon{margin-right:.5em}details.sd-dropdown .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary:hover .sd-summary-up svg,details.sd-dropdown summary:hover .sd-summary-down svg{opacity:1;transform:scale(1.1)}details.sd-dropdown .sd-summary-up svg,details.sd-dropdown .sd-summary-down svg{display:block;opacity:.6}details.sd-dropdown .sd-summary-up,details.sd-dropdown .sd-summary-down{pointer-events:none;position:absolute;right:1em;top:1em}details.sd-dropdown[open]>.sd-summary-title .sd-summary-down{visibility:hidden}details.sd-dropdown:not([open])>.sd-summary-title .sd-summary-up{visibility:hidden}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #0071bc;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0060a0;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem} diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_static/design-tabs.js b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/design-tabs.js new file mode 100644 index 00000000000..36b38cf0d91 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/design-tabs.js @@ -0,0 +1,27 @@ +var sd_labels_by_text = {}; + +function ready() { + const li = document.getElementsByClassName("sd-tab-label"); + for (const label of li) { + syncId = label.getAttribute("data-sync-id"); + if (syncId) { + label.onclick = onLabelClick; + if (!sd_labels_by_text[syncId]) { + sd_labels_by_text[syncId] = []; + } + sd_labels_by_text[syncId].push(label); + } + } +} + +function onLabelClick() { + // Activate other inputs with the same sync id. + syncId = this.getAttribute("data-sync-id"); + for (label of sd_labels_by_text[syncId]) { + if (label === this) continue; + label.previousElementSibling.checked = true; + } + window.localStorage.setItem("sphinx-design-last-tab", syncId); +} + +document.addEventListener("DOMContentLoaded", ready, false); diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_static/doctools.js b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/doctools.js new file mode 100644 index 00000000000..527b876ca63 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_static/documentation_options.js b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/documentation_options.js new file mode 100644 index 00000000000..44789c22137 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/documentation_options.js @@ -0,0 +1,14 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '1.0.4', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_static/file.png b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 GIT binary patch literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( literal 0 HcmV?d00001 diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_static/graphviz.css b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/graphviz.css new file mode 100644 index 00000000000..19e7afd385b --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/graphviz.css @@ -0,0 +1,19 @@ +/* + * graphviz.css + * ~~~~~~~~~~~~ + * + * Sphinx stylesheet -- graphviz extension. + * + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +img.graphviz { + border: 0; + max-width: 100%; +} + +object.graphviz { + max-width: 100%; +} diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/_static/jquery-3.6.0.js b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/jquery-3.6.0.js new file mode 100644 index 00000000000..fc6c299b73e --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/_static/jquery-3.6.0.js @@ -0,0 +1,10881 @@ +/*! + * jQuery JavaScript Library v3.6.0 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2021-03-02T17:08Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5 + // Plus for old WebKit, typeof returns "function" for HTML collections + // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756) + return typeof obj === "function" && typeof obj.nodeType !== "number" && + typeof obj.item !== "function"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.6.0", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), + function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); + } ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.6 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2021-02-16 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem && elem.namespaceURI, + docElem = elem && ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +} +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the primary Deferred + primary = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + primary.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( primary.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return primary.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject ); + } + + return primary.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + + // Support: Chrome 86+ + // In Chrome, if an element having a focusout handler is blurred by + // clicking outside of it, it invokes the handler synchronously. If + // that handler calls `.remove()` on the element, the data is cleared, + // leaving `result` undefined. We need to guard against this. + return result && result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + which: true +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + // Suppress native focus or blur as it's already being fired + // in leverageNative. + _default: function() { + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + // + // Support: Firefox 70+ + // Only Firefox includes border widths + // in computed dimensions. (gh-4529) + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate"; + tr.style.cssText = "border:1px solid"; + + // Support: Chrome 86+ + // Height set through cssText does not get applied. + // Computed height then comes back as 0. + tr.style.height = "1px"; + trChild.style.height = "9px"; + + // Support: Android 8 Chrome 86+ + // In our bodyBackground.html iframe, + // display for all div elements is set to "inline", + // which causes a problem only in Android 8 Chrome 86. + // Ensuring the div is display: block + // gets around this issue. + trChild.style.display = "block"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) + + parseInt( trStyle.borderTopWidth, 10 ) + + parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml, parserErrorElem; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) {} + + parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ]; + if ( !xml || parserErrorElem ) { + jQuery.error( "Invalid XML: " + ( + parserErrorElem ? + jQuery.map( parserErrorElem.childNodes, function( el ) { + return el.textContent; + } ).join( "\n" ) : + data + ) ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ).filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ).map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + +originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script but not if jsonp + if ( !isSuccess && + jQuery.inArray( "script", s.dataTypes ) > -1 && + jQuery.inArray( "json", s.dataTypes ) < 0 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

Access Control

+

Access Control of Airflow Webserver UI is handled by Flask AppBuilder (FAB). +Please read its related security document +regarding its security model.

+
+

Default Roles

+

Airflow ships with a set of roles by default: Admin, User, Op, Viewer, and Public. +By default, only Admin users can configure/alter permissions for roles. However, +it is recommended that these default roles remain unaltered, and instead Admin users +create new roles with the desired permissions if changes are necessary.

+
+

Public

+

Public users (anonymous) don’t have any permissions.

+
+
+

Viewer

+

Viewer users have limited read permissions:

+
+

airflow/providers/fab/auth_manager/security_manager/override.py[source]

+
    VIEWER_PERMISSIONS = [
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_DEPENDENCIES),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_CODE),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_RUN),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_DATASET),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_CLUSTER_ACTIVITY),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_POOL),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_IMPORT_ERROR),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_WARNING),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_JOB),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_MY_PASSWORD),
+        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_MY_PASSWORD),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_MY_PROFILE),
+        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_MY_PROFILE),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_PLUGIN),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_SLA_MISS),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_TASK_INSTANCE),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_TASK_LOG),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_XCOM),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_WEBSITE),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_BROWSE_MENU),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DAG),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DAG_DEPENDENCIES),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DAG_RUN),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DATASET),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_CLUSTER_ACTIVITY),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DOCS),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DOCS_MENU),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_JOB),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_PLUGIN),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_SLA_MISS),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_TASK_INSTANCE),
+    ]
+
+
+
+
+
+

User

+

User users have Viewer permissions plus additional permissions:

+
+

airflow/providers/fab/auth_manager/security_manager/override.py[source]

+
    USER_PERMISSIONS = [
+        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_DAG),
+        (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_DAG),
+        (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_TASK_INSTANCE),
+        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_TASK_INSTANCE),
+        (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_TASK_INSTANCE),
+        (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_DAG_RUN),
+        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_DAG_RUN),
+        (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_DAG_RUN),
+        (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_DATASET),
+    ]
+
+
+
+
+
+

Op

+

Op users have User permissions plus additional permissions:

+
+

airflow/providers/fab/auth_manager/security_manager/override.py[source]

+
    OP_PERMISSIONS = [
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_CONFIG),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_ADMIN_MENU),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_CONFIG),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_CONNECTION),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_POOL),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_VARIABLE),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_PROVIDER),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_XCOM),
+        (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_CONNECTION),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_CONNECTION),
+        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_CONNECTION),
+        (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_CONNECTION),
+        (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_POOL),
+        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_POOL),
+        (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_POOL),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_PROVIDER),
+        (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_VARIABLE),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_VARIABLE),
+        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_VARIABLE),
+        (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_VARIABLE),
+        (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_XCOM),
+        (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_DATASET),
+        (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_DATASET),
+    ]
+
+
+
+
+
+

Admin

+

Admin users have all possible permissions, including granting or revoking permissions from +other users. Admin users have Op permission plus additional permissions:

+
+

airflow/providers/fab/auth_manager/security_manager/override.py[source]

+
    ADMIN_PERMISSIONS = [
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_AUDIT_LOG),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_AUDIT_LOG),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_TASK_RESCHEDULE),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_TASK_RESCHEDULE),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_TRIGGER),
+        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_TRIGGER),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_PASSWORD),
+        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_PASSWORD),
+        (permissions.ACTION_CAN_READ, permissions.RESOURCE_ROLE),
+        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_ROLE),
+    ]
+
+
+
+
+
+
+

Custom Roles

+
+

DAG Level Role

+

Admin can create a set of roles which are only allowed to view a certain set of DAGs. This is called DAG level access. Each DAG defined in the DAG model table +is treated as a View which has two permissions associated with it (can_read and can_edit. can_dag_read and can_dag_edit are deprecated since 2.0.0). +There is a special view called DAGs (it was called all_dags in versions 1.10.*) which +allows the role to access all the DAGs. The default Admin, Viewer, User, Op roles can all access DAGs view.

+../_images/add-role.png +../_images/new-role.png +

The image shows the creation of a role which can only write to +example_python_operator. You can also create roles via the CLI +using the airflow roles create command, e.g.:

+
airflow roles create Role1 Role2
+
+
+

And we could assign the given role to a new user using the airflow +users add-role CLI command.

+
+
+
+

Permissions

+
+

Resource-Based permissions

+

Starting with version 2.0, permissions are based on individual resources and a small subset of actions on those +resources. Resources match standard Airflow concepts, such as Dag, DagRun, Task, and +Connection. Actions include can_create, can_read, can_edit, and can_delete.

+

Permissions (each consistent of a resource + action pair) are then added to roles.

+

To access an endpoint, the user needs all permissions assigned to that endpoint

+

There are five default roles: Public, Viewer, User, Op, and Admin. Each one has the permissions of the preceding role, as well as additional permissions.

+
+
+

DAG-level permissions

+

For DAG-level permissions exclusively, access can be controlled at the level of all DAGs or individual DAG objects. This includes DAGs.can_read, DAGs.can_edit, and DAGs.can_delete. When these permissions are listed, access is granted to users who either have the listed permission or the same permission for the specific DAG being acted upon. For individual DAGs, the resource name is DAG: + the DAG ID.

+

For example, if a user is trying to view DAG information for the example_dag_id, and the endpoint requires DAGs.can_read access, access will be granted if the user has either DAGs.can_read or DAG:example_dag_id.can_read access.

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Stable API Permissions

Endpoint

Method

Permissions

Minimum Role

/config

GET

Configurations.can_read

Op

/connections

GET

Connections.can_read

Op

/connections

POST

Connections.can_create

Op

/connections/{connection_id}

DELETE

Connections.can_delete

Op

/connections/{connection_id}

PATCH

Connections.can_edit

Op

/connections/{connection_id}

GET

Connections.can_read

Op

/dagSources/{file_token}

GET

DAG Code.can_read

Viewer

/dags

GET

DAGs.can_read

Viewer

/dags/{dag_id}

GET

DAGs.can_read

Viewer

/dags/{dag_id}

PATCH

DAGs.can_edit

User

/dags/{dag_id}/clearTaskInstances

POST

DAGs.can_edit, DAG Runs.can_read, Task Instances.can_edit

User

/dags/{dag_id}/details

GET

DAGs.can_read

Viewer

/dags/{dag_id}/tasks

GET

DAGs.can_read, Task Instances.can_read

Viewer

/dags/{dag_id}/tasks/{task_id}

GET

DAGs.can_read, Task Instances.can_read

Viewer

/dags/{dag_id}/dagRuns

GET

DAGs.can_read, DAG Runs.can_read

Viewer

/dags/{dag_id}/dagRuns

POST

DAGs.can_edit, DAG Runs.can_create

User

/dags/{dag_id}/dagRuns/{dag_run_id}

DELETE

DAGs.can_edit, DAG Runs.can_delete

User

/dags/{dag_id}/dagRuns/{dag_run_id}

GET

DAGs.can_read, DAG Runs.can_read

Viewer

/dags/~/dagRuns/list

POST

DAGs.can_edit, DAG Runs.can_read

User

/datasets

GET

Datasets.can_read

Viewer

/datasets/{uri}

GET

Datasets.can_read

Viewer

/datasets/events

GET

Datasets.can_read

Viewer

/eventLogs

GET

Audit Logs.can_read

Viewer

/eventLogs/{event_log_id}

GET

Audit Logs.can_read

Viewer

/importErrors

GET

ImportError.can_read

Viewer

/importErrors/{import_error_id}

GET

ImportError.can_read

Viewer

/health

GET

None

Public

/version

GET

None

Public

/pools

GET

Pools.can_read

Op

/pools

POST

Pools.can_create

Op

/pools/{pool_name}

DELETE

Pools.can_delete

Op

/pools/{pool_name}

GET

Pools.can_read

Op

/pools/{pool_name}

PATCH

Pools.can_edit

Op

/providers

GET

Providers.can_read

Op

/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances

GET

DAGs.can_read, DAG Runs.can_read, Task Instances.can_read

Viewer

/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}

GET

DAGs.can_read, DAG Runs.can_read, Task Instances.can_read

Viewer

/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/links

GET

DAGs.can_read, DAG Runs.can_read, Task Instances.can_read

Viewer

/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/logs/{task_try_number}

GET

DAGs.can_read, DAG Runs.can_read, Task Instances.can_read

Viewer

/dags/~/dagRuns/~/taskInstances/list

POST

DAGs.can_edit, DAG Runs.can_read, Task Instances.can_read

User

/variables

GET

Variables.can_read

Op

/variables

POST

Variables.can_create

Op

/variables/{variable_key}

DELETE

Variables.can_delete

Op

/variables/{variable_key}

GET

Variables.can_read

Op

/variables/{variable_key}

PATCH

Variables.can_edit

Op

/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/xcomEntries

GET

DAGs.can_read, DAG Runs.can_read, +Task Instances.can_read, XComs.can_read

Viewer

/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/xcomEntries/{xcom_key}

GET

DAGs.can_read, DAG Runs.can_read, +Task Instances.can_read, XComs.can_read

Viewer

/users

GET

Users.can_read

Admin

/users

POST

Users.can_create

Admin

/users/{username}

GET

Users.can_read

Admin

/users/{username}

PATCH

Users.can_edit

Admin

/users/{username}

DELETE

Users.can_delete

Admin

/roles

GET

Roles.can_read

Admin

/roles

POST

Roles.can_create

Admin

/roles/{role_name}

GET

Roles.can_read

Admin

/roles/{role_name}

PATCH

Roles.can_edit

Admin

/roles/{role_name}

DELETE

Roles.can_delete

Admin

/permissions

GET

Permission Views.can_read

Admin

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Website Permissions

Action

Permissions

Minimum Role

Access homepage

Website.can_read

Viewer

Show Browse menu

Browse.menu_access

Viewer

Show DAGs menu

DAGs.menu_access

Viewer

Get DAG stats

DAGs.can_read, DAG Runs.can_read

Viewer

Show Task Instances menu

Task Instances.menu_access

Viewer

Get Task stats

DAGs.can_read, DAG Runs.can_read, Task Instances.can_read

Viewer

Get last DAG runs

DAGs.can_read, DAG Runs.can_read

Viewer

Get DAG code

DAGs.can_read, DAG Code.can_read

Viewer

Get DAG details

DAGs.can_read, DAG Runs.can_read

Viewer

Show DAG Dependencies menu

DAG Dependencies.menu_access

Viewer

Get DAG Dependencies

DAG Dependencies.can_read

Viewer

Get rendered DAG

DAGs.can_read, Task Instances.can_read

Viewer

Get Logs with metadata

DAGs.can_read, Task Instances.can_read, Task Logs.can_read

Viewer

Get Log

DAGs.can_read, Task Instances.can_read, Task Logs.can_read

Viewer

Redirect to external Log

DAGs.can_read, Task Instances.can_read, Task Logs.can_read

Viewer

Get Task

DAGs.can_read, Task Instances.can_read

Viewer

Show XCom menu

XComs.menu_access

Op

Get XCom

DAGs.can_read, Task Instances.can_read, XComs.can_read

Viewer

Create XCom

XComs.can_create

Op

Delete XCom

XComs.can_delete

Op

Triggers Task Instance

DAGs.can_edit, Task Instances.can_create

User

Delete DAG

DAGs.can_delete

User

Show DAG Runs menu

DAG Runs.menu_access

Viewer

Trigger DAG run

DAGs.can_edit, DAG Runs.can_create

User

Clear DAG

DAGs.can_edit, Task Instances.can_delete

User

Clear DAG Run

DAGs.can_edit, Task Instances.can_delete

User

Mark DAG as blocked

DAGS.can_edit, DAG Runs.can_read

User

Mark DAG Run as failed

DAGS.can_edit, DAG Runs.can_edit

User

Mark DAG Run as success

DAGS.can_edit, DAG Runs.can_edit

User

Mark Task as failed

DAGs.can_edit, Task Instances.can_edit

User

Mark Task as success

DAGs.can_edit, Task Instances.can_edit

User

Get DAG as tree

DAGs.can_read, Task Instances.can_read, +Task Logs.can_read

Viewer

Get DAG as graph

DAGs.can_read, Task Instances.can_read, +Task Logs.can_read

Viewer

Get DAG as duration graph

DAGs.can_read, Task Instances.can_read

Viewer

Show all tries

DAGs.can_read, Task Instances.can_read

Viewer

Show landing times

DAGs.can_read, Task Instances.can_read

Viewer

Toggle DAG paused status

DAGs.can_edit

User

Show Gantt Chart

DAGs.can_read, Task Instances.can_read

Viewer

Get external links

DAGs.can_read, Task Instances.can_read

Viewer

Show Task Instances

DAGs.can_read, Task Instances.can_read

Viewer

Show Configurations menu

Configurations.menu_access

Op

Show Configs

Configurations.can_read

Viewer

Delete multiple records

DAGs.can_edit

User

Set Task Instance as running

DAGs.can_edit

User

Set Task Instance as failed

DAGs.can_edit

User

Set Task Instance as success

DAGs.can_edit

User

Set Task Instance as up_for_retry

DAGs.can_edit

User

Autocomplete

DAGs.can_read

Viewer

Show Dataset menu

Datasets.menu_access

Viewer

Show Datasets

Datasets.can_read

Viewer

Show Docs menu

Docs.menu_access

Viewer

Show Documentation menu

Documentation.menu_access

Viewer

Show Jobs menu

Jobs.menu_access

Viewer

Show Audit Log

Audit Logs.menu_access

Viewer

Reset Password

My Password.can_read, My Password.can_edit

Viewer

Show Permissions menu

Permission Views.menu_access

Admin

List Permissions

Permission Views.can_read

Admin

Get My Profile

My Profile.can_read

Viewer

Update My Profile

My Profile.can_edit

Viewer

List Logs

Audit Logs.can_read

Viewer

List Jobs

Jobs.can_read

Viewer

Show SLA Misses menu

SLA Misses.menu_access

Viewer

List SLA Misses

SLA Misses.can_read

Viewer

List Plugins

Plugins.can_read

Viewer

Show Plugins menu

Plugins.menu_access

Viewer

Show Providers menu

Providers.menu_access

Op

List Providers

Providers.can_read

Op

List Task Reschedules

Task Reschedules.can_read

Admin

Show Triggers menu

Triggers.menu_access

Admin

List Triggers

Triggers.can_read

Admin

Show Admin menu

Admin.menu_access

Viewer

Show Connections menu

Connections.menu_access

Op

Show Pools menu

Pools.menu_access

Viewer

Show Variables menu

Variables.menu_access

Op

Show Roles menu

Roles.menu_access

Admin

List Roles

Roles.can_read

Admin

Create Roles

Roles.can_create

Admin

Update Roles

Roles.can_edit

Admin

Delete Roles

Roles.can_delete

Admin

Show Users menu

Users.menu_access

Admin

Create Users

Users.can_create

Admin

Update Users

Users.can_edit

Admin

Delete Users

Users.can_delete

Admin

Reset user Passwords

Passwords.can_edit, Passwords.can_read

Admin

+

These DAG-level controls can be set directly through the UI / CLI, or encoded in the dags themselves through the access_control arg.

+
+
+

Order of precedence for DAG-level permissions

+

Since DAG-level access control can be configured in multiple places, conflicts are inevitable and a clear resolution strategy is required. As a result, +Airflow considers the access_control argument supplied on a DAG itself to be completely authoritative if present, which has a few effects:

+

Setting access_control on a DAG will overwrite any previously existing DAG-level permissions if it is any value other than None:

+
DAG(
+    dag_id="example_fine_grained_access",
+    start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
+    access_control={
+        "Viewer": {"can_edit", "can_read", "can_delete"},
+    },
+)
+
+
+

This also means that setting access_control={} will wipe any existing DAG-level permissions for a given DAG from the DB:

+
DAG(
+    dag_id="example_no_fine_grained_access",
+    start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
+    access_control={},
+)
+
+
+

Conversely, removing the access_control block from a DAG altogether (or setting it to None) won’t make any changes and can leave dangling permissions.

+
DAG(
+    dag_id="example_indifferent_to_fine_grained_access",
+    start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
+)
+
+
+

In the case that there is no access_control defined on the DAG itself, Airflow will defer to existing permissions defined in the DB, which +may have been set through the UI, CLI or by previous access_control args on the DAG in question.

+

In all cases, system-wide roles such as Can edit on DAG take precedence over dag-level access controls, such that they can be considered Can edit on DAG: *

+
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/auth-manager/api-authentication.html b/docs-archive/apache-airflow-providers-fab/1.0.4/auth-manager/api-authentication.html new file mode 100644 index 00000000000..d1f65459ad4 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/auth-manager/api-authentication.html @@ -0,0 +1,970 @@ + + + + + + + + + + + + API Authentication — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

API Authentication

+

Authentication for the API is handled separately to the Web Authentication. The default is to +check the user session:

+
[api]
+auth_backends = airflow.api.auth.backend.session
+
+
+
+

Changed in version 1.10.11: In Airflow <1.10.11, the default setting was to allow all API requests without authentication, but this +posed security risks for if the Webserver is publicly accessible.

+
+
+

Changed in version 2.3.0: In Airflow <2.3.0 this setting was auth_backend and allowed only one +value. In 2.3.0 it was changed to support multiple backends that are tried +in turn.

+
+

If you want to check which authentication backends are currently set, you can use airflow config get-value api auth_backends +command as in the example below.

+
$ airflow config get-value api auth_backends
+airflow.api.auth.backend.basic_auth
+
+
+
+

Disable authentication

+

If you wish to have the experimental API work, and aware of the risks of enabling this without authentication +(or if you have your own authentication layer in front of Airflow) you can set the following in airflow.cfg:

+
[api]
+auth_backends = airflow.api.auth.backend.default
+
+
+
+

Note

+

You can only disable authentication for experimental API, not the stable REST API.

+
+

See Modules Management for details on how Python and Airflow manage modules.

+
+
+

Kerberos authentication

+

Kerberos authentication is currently supported for the API.

+

To enable Kerberos authentication, set the following in the configuration:

+
[api]
+auth_backends = airflow.api.auth.backend.kerberos_auth
+
+[kerberos]
+keytab = <KEYTAB>
+
+
+

The Kerberos service is configured as airflow/fully.qualified.domainname@REALM. Make sure this +principal exists in the keytab file.

+

You have to make sure to name your users with the kerberos full username/realm in order to make it +works. This means that your user name should be user_name@KERBEROS-REALM.

+
+
+

Basic authentication

+

Basic username password authentication is currently +supported for the API. This works for users created through LDAP login or +within Airflow Metadata DB using password.

+

To enable basic authentication, set the following in the configuration:

+
[api]
+auth_backends = airflow.api.auth.backend.basic_auth
+
+
+

Username and password needs to be base64 encoded and send through the +Authorization HTTP header in the following format:

+
Authorization: Basic Base64(username:password)
+
+
+

Here is a sample curl command you can use to validate the setup:

+
ENDPOINT_URL="http://localhost:8080/"
+curl -X GET  \
+    --user "username:password" \
+    "${ENDPOINT_URL}/api/v1/pools"
+
+
+

Note, you can still enable this setting to allow API access through username +password credential even though Airflow webserver might be using another +authentication method. Under this setup, only users created through LDAP or +airflow users create command will be able to pass the API authentication.

+
+
+

Roll your own API authentication

+

Each auth backend is defined as a new Python module. It must have 2 defined methods:

+
    +
  • init_app(app: Flask) - function invoked when creating a flask application, which allows you to add a new view.

  • +
  • requires_authentication(fn: Callable) - a decorator that allows arbitrary code execution before and after or instead of a view function.

  • +
+

and may have one of the following to support API client authorizations used by remote mode for CLI:

+
    +
  • function create_client_session() -> requests.Session

  • +
  • attribute CLIENT_AUTH: tuple[str, str] | requests.auth.AuthBase | None

  • +
+

After writing your backend module, provide the fully qualified module name in the auth_backends key in the [api] +section of airflow.cfg.

+

Additional options to your auth backend can be configured in airflow.cfg, as a new option.

+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/auth-manager/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/auth-manager/index.html new file mode 100644 index 00000000000..2497be543e5 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/auth-manager/index.html @@ -0,0 +1,879 @@ + + + + + + + + + + + + Flask AppBuilder (FAB) auth manager — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

Flask AppBuilder (FAB) auth manager

+

FAB auth (for authentication/authorization) manager is the auth manager that comes by default with Airflow. This auth manager defines the user authentication and user authorization by default in Airflow. +The backend used to store all entities used by the FAB auth manager is the Airflow database: ERD Schema of the Database.

+../_images/diagram_fab_auth_manager_airflow_architecture.png +

Follow the below topics as well to understand other aspects of FAB auth manager:

+ +
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/auth-manager/webserver-authentication.html b/docs-archive/apache-airflow-providers-fab/1.0.4/auth-manager/webserver-authentication.html new file mode 100644 index 00000000000..0727f272aec --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/auth-manager/webserver-authentication.html @@ -0,0 +1,1067 @@ + + + + + + + + + + + + Webserver authentication — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

Webserver authentication

+

By default, Airflow requires users to specify a password prior to login. You can use the +following CLI commands to create an account:

+
# create an admin user
+airflow users create \
+    --username admin \
+    --firstname Peter \
+    --lastname Parker \
+    --role Admin \
+    --email spiderman@superhero.org
+
+
+

To deactivate the authentication and allow users to be identified as Anonymous, the following entry +in $AIRFLOW_HOME/webserver_config.py needs to be set with the desired role that the Anonymous +user will have by default:

+
AUTH_ROLE_PUBLIC = 'Admin'
+
+
+

Be sure to checkout API for securing the API.

+
+

Note

+

Airflow uses the config parser of Python. This config parser interpolates +‘%’-signs. Make sure escape any % signs in your config file (but not +environment variables) as %%, otherwise Airflow might leak these +passwords on a config parser exception to a log.

+
+
+

Password

+

One of the simplest mechanisms for authentication is requiring users to specify a password before logging in.

+

Please use command line interface airflow users create to create accounts, or do that in the UI.

+
+
+

Other Methods

+

Since Airflow 2.0, the default UI is the Flask App Builder RBAC. A webserver_config.py configuration file +is automatically generated and can be used to configure the Airflow to support authentication +methods like OAuth, OpenID, LDAP, REMOTE_USER. It should be noted that due to the limitation of Flask AppBuilder +and Authlib, only a selection of OAuth2 providers is supported. This list includes github, githublocal, twitter, +linkedin, google, azure, openshift, okta, keycloak and keycloak_before_17.

+

The default authentication option described in the Web Authentication section is related +with the following entry in the $AIRFLOW_HOME/webserver_config.py.

+
AUTH_TYPE = AUTH_DB
+
+
+

A WSGI middleware could be used to manage very specific forms of authentication +(e.g. SPNEGO) +and leverage the REMOTE_USER method:

+
from typing import Any, Callable
+
+from flask import current_app
+from flask_appbuilder.const import AUTH_REMOTE_USER
+
+
+class CustomMiddleware:
+    def __init__(self, wsgi_app: Callable) -> None:
+        self.wsgi_app = wsgi_app
+
+    def __call__(self, environ: dict, start_response: Callable) -> Any:
+        # Custom authenticating logic here
+        # ...
+        environ["REMOTE_USER"] = "username"
+        return self.wsgi_app(environ, start_response)
+
+
+current_app.wsgi_app = CustomMiddleware(current_app.wsgi_app)
+
+AUTH_TYPE = AUTH_REMOTE_USER
+
+
+

Another way to create users is in the UI login page, allowing user self registration through a “Register” button. +The following entries in the $AIRFLOW_HOME/webserver_config.py can be edited to make it possible:

+
AUTH_USER_REGISTRATION = True
+AUTH_USER_REGISTRATION_ROLE = "Desired Role For The Self Registered User"
+RECAPTCHA_PRIVATE_KEY = 'private_key'
+RECAPTCHA_PUBLIC_KEY = 'public_key'
+
+MAIL_SERVER = 'smtp.gmail.com'
+MAIL_USE_TLS = True
+MAIL_USERNAME = 'yourappemail@gmail.com'
+MAIL_PASSWORD = 'passwordformail'
+MAIL_DEFAULT_SENDER = 'sender@gmail.com'
+
+
+

The package Flask-Mail needs to be installed through pip to allow user self registration since it is a +feature provided by the framework Flask-AppBuilder.

+

To support authentication through a third-party provider, the AUTH_TYPE entry needs to be updated with the +desired option like OAuth, OpenID, LDAP, and the lines with references for the chosen option need to have +the comments removed and configured in the $AIRFLOW_HOME/webserver_config.py.

+

For more details, please refer to +Security section of FAB documentation.

+
+
+

Example using team based Authorization with GitHub OAuth

+

There are a few steps required in order to use team-based authorization with GitHub OAuth.

+
    +
  • configure OAuth through the FAB config in webserver_config.py

  • +
  • create a custom security manager class and supply it to FAB in webserver_config.py

  • +
  • map the roles returned by your security manager class to roles that FAB understands.

  • +
+

Here is an example of what you might have in your webserver_config.py:

+
from airflow.auth.managers.fab.security_manager.override import FabAirflowSecurityManagerOverride
+from flask_appbuilder.security.manager import AUTH_OAUTH
+import os
+
+AUTH_TYPE = AUTH_OAUTH
+AUTH_ROLES_SYNC_AT_LOGIN = True  # Checks roles on every login
+AUTH_USER_REGISTRATION = True  # allow users who are not already in the FAB DB to register
+
+AUTH_ROLES_MAPPING = {
+    "Viewer": ["Viewer"],
+    "Admin": ["Admin"],
+}
+# If you wish, you can add multiple OAuth providers.
+OAUTH_PROVIDERS = [
+    {
+        "name": "github",
+        "icon": "fa-github",
+        "token_key": "access_token",
+        "remote_app": {
+            "client_id": os.getenv("OAUTH_APP_ID"),
+            "client_secret": os.getenv("OAUTH_APP_SECRET"),
+            "api_base_url": "https://api.github.com",
+            "client_kwargs": {"scope": "read:user, read:org"},
+            "access_token_url": "https://github.com/login/oauth/access_token",
+            "authorize_url": "https://github.com/login/oauth/authorize",
+            "request_token_url": None,
+        },
+    },
+]
+
+
+class CustomSecurityManager(FabAirflowSecurityManagerOverride):
+    pass
+
+
+# Make sure to replace this with your own implementation of AirflowSecurityManager class
+SECURITY_MANAGER_CLASS = CustomSecurityManager
+
+
+

Here is an example of defining a custom security manager. +This class must be available in Python’s path, and could be defined in +webserver_config.py itself if you wish.

+
from airflow.auth.managers.fab.security_manager.override import FabAirflowSecurityManagerOverride
+import logging
+from typing import Any, List, Union
+import os
+
+log = logging.getLogger(__name__)
+log.setLevel(os.getenv("AIRFLOW__LOGGING__FAB_LOGGING_LEVEL", "INFO"))
+
+FAB_ADMIN_ROLE = "Admin"
+FAB_VIEWER_ROLE = "Viewer"
+FAB_PUBLIC_ROLE = "Public"  # The "Public" role is given no permissions
+TEAM_ID_A_FROM_GITHUB = 123  # Replace these with real team IDs for your org
+TEAM_ID_B_FROM_GITHUB = 456  # Replace these with real team IDs for your org
+
+
+def team_parser(team_payload: dict[str, Any]) -> list[int]:
+    # Parse the team payload from GitHub however you want here.
+    return [team["id"] for team in team_payload]
+
+
+def map_roles(team_list: list[int]) -> list[str]:
+    # Associate the team IDs with Roles here.
+    # The expected output is a list of roles that FAB will use to Authorize the user.
+
+    team_role_map = {
+        TEAM_ID_A_FROM_GITHUB: FAB_ADMIN_ROLE,
+        TEAM_ID_B_FROM_GITHUB: FAB_VIEWER_ROLE,
+    }
+    return list(set(team_role_map.get(team, FAB_PUBLIC_ROLE) for team in team_list))
+
+
+class GithubTeamAuthorizer(FabAirflowSecurityManagerOverride):
+    # In this example, the oauth provider == 'github'.
+    # If you ever want to support other providers, see how it is done here:
+    # https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/security/manager.py#L550
+    def get_oauth_user_info(self, provider: str, resp: Any) -> dict[str, Union[str, list[str]]]:
+        # Creates the user info payload from Github.
+        # The user previously allowed your app to act on their behalf,
+        #   so now we can query the user and teams endpoints for their data.
+        # Username and team membership are added to the payload and returned to FAB.
+
+        remote_app = self.appbuilder.sm.oauth_remotes[provider]
+        me = remote_app.get("user")
+        user_data = me.json()
+        team_data = remote_app.get("user/teams")
+        teams = team_parser(team_data.json())
+        roles = map_roles(teams)
+        log.debug(f"User info from Github: {user_data}\nTeam info from Github: {teams}")
+        return {"username": "github_" + user_data.get("login"), "role_keys": roles}
+
+
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/changelog.html b/docs-archive/apache-airflow-providers-fab/1.0.4/changelog.html new file mode 100644 index 00000000000..76c9098228c --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/changelog.html @@ -0,0 +1,910 @@ + + + + + + + + + + + + Changelog — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+
+

apache-airflow-providers-fab

+
+

Changelog

+
+

1.0.4

+
+

Bug Fixes

+
    +
  • Remove button for reset my password when we have reset password (#38957)

  • +
+
+
+
+

1.0.3

+
+

Bug Fixes

+
    +
  • Rename 'allowed_filter_attrs' to 'allowed_sort_attrs' (#38626)

  • +
  • Fix azure authentication when no email is set (#38872)

  • +
+
+
+
+

1.0.2

+

First stable release for the provider

+
+
+

1.0.0 (YANKED)

+

Initial version of the provider (beta).

+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/cli-ref.html b/docs-archive/apache-airflow-providers-fab/1.0.4/cli-ref.html new file mode 100644 index 00000000000..700472a694b --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/cli-ref.html @@ -0,0 +1,1462 @@ + + + + + + + + + + + + FAB CLI Commands — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

FAB CLI Commands

+
+

Note

+

The CLI commands below are sourced from the FAB provider by Airflow 2.9.0+. +Previously, they were part of core Airflow, so if you are using Airflow below 2.9.0 please see +the core Airflow documentation for the list of CLI commands and parameters available.

+
+
Usage: airflow [-h] GROUP_OR_COMMAND ...
+
+
+
+

Positional Arguments

+
+
GROUP_OR_COMMAND
+

Possible choices: users, roles, sync-perm

+
+
+
+
+

Sub-commands

+
+

users

+

Manage users

+
airflow users [-h] COMMAND ...
+
+
+
+

Positional Arguments

+
+
COMMAND
+

Possible choices: add-role, create, delete, export, import, list, remove-role, reset-password

+
+
+
+
+

Sub-commands

+
+
add-role
+

Add role to a user

+
airflow users add-role [-h] [-e EMAIL] -r ROLE [-u USERNAME] [-v]
+
+
+
+
Named Arguments
+
+
-e, --email
+

Email of the user

+
+
-r, --role
+

Role of the user. Existing roles include Admin, User, Op, Viewer, and Public

+
+
-u, --username
+

Username of the user

+
+
-v, --verbose
+

Make logging output more verbose

+

Default: False

+
+
+
+
+
+
create
+

Create a user

+
airflow users create [-h] -e EMAIL -f FIRSTNAME -l LASTNAME [-p PASSWORD] -r
+                     ROLE [--use-random-password] -u USERNAME [-v]
+
+
+
+
Named Arguments
+
+
-e, --email
+

Email of the user

+
+
-f, --firstname
+

First name of the user

+
+
-l, --lastname
+

Last name of the user

+
+
-p, --password
+

Password of the user, required to create a user without –use-random-password

+
+
-r, --role
+

Role of the user. Existing roles include Admin, User, Op, Viewer, and Public

+
+
--use-random-password
+

Do not prompt for password. Use random string instead. Required to create a user without –password

+

Default: False

+
+
-u, --username
+

Username of the user

+
+
-v, --verbose
+

Make logging output more verbose

+

Default: False

+
+
+
+

examples: +To create an user with “Admin” role and username equals to “admin”, run:

+
+
+
$ airflow users create

–username admin –firstname FIRST_NAME –lastname LAST_NAME –role Admin –email admin@example.org

+
+
+
+
+
+
delete
+

Delete a user

+
airflow users delete [-h] [-e EMAIL] [-u USERNAME] [-v]
+
+
+
+
Named Arguments
+
+
-e, --email
+

Email of the user

+
+
-u, --username
+

Username of the user

+
+
-v, --verbose
+

Make logging output more verbose

+

Default: False

+
+
+
+
+
+
export
+

Export all users

+
airflow users export [-h] [-v] FILEPATH
+
+
+
+
Positional Arguments
+
+
FILEPATH
+

Export all users to JSON file

+
+
+
+
+
Named Arguments
+
+
-v, --verbose
+

Make logging output more verbose

+

Default: False

+
+
+
+
+
+
import
+

Import users

+
airflow users import [-h] [-v] FILEPATH
+
+
+
+
Positional Arguments
+
+
FILEPATH
+

Import users from JSON file. Example format:

+
[
+    {
+        "email": "foo@bar.org",
+        "firstname": "Jon",
+        "lastname": "Doe",
+        "roles": ["Public"],
+        "username": "jondoe"
+    }
+]
+
+
+
+
+
+
+
Named Arguments
+
+
-v, --verbose
+

Make logging output more verbose

+

Default: False

+
+
+
+
+
+
list
+

List users

+
airflow users list [-h] [-o table, json, yaml, plain] [-v]
+
+
+
+
Named Arguments
+
+
-o, --output
+

Possible choices: table, json, yaml, plain

+

Output format. Allowed values: json, yaml, plain, table (default: table)

+

Default: “table”

+
+
-v, --verbose
+

Make logging output more verbose

+

Default: False

+
+
+
+
+
+
remove-role
+

Remove role from a user

+
airflow users remove-role [-h] [-e EMAIL] -r ROLE [-u USERNAME] [-v]
+
+
+
+
Named Arguments
+
+
-e, --email
+

Email of the user

+
+
-r, --role
+

Role of the user. Existing roles include Admin, User, Op, Viewer, and Public

+
+
-u, --username
+

Username of the user

+
+
-v, --verbose
+

Make logging output more verbose

+

Default: False

+
+
+
+
+
+
reset-password
+

Reset a user’s password

+
airflow users reset-password [-h] [-e EMAIL] [-p PASSWORD]
+                             [--use-random-password] [-u USERNAME] [-v]
+
+
+
+
Named Arguments
+
+
-e, --email
+

Email of the user

+
+
-p, --password
+

Password of the user, required to create a user without –use-random-password

+
+
--use-random-password
+

Do not prompt for password. Use random string instead. Required to create a user without –password

+

Default: False

+
+
-u, --username
+

Username of the user

+
+
-v, --verbose
+

Make logging output more verbose

+

Default: False

+
+
+
+

examples: +To reset an user with username equals to “admin”, run:

+
+
+
$ airflow users reset-password

–username admin

+
+
+
+
+
+
+
+

roles

+

Manage roles

+
airflow roles [-h] COMMAND ...
+
+
+
+

Positional Arguments

+
+
COMMAND
+

Possible choices: add-perms, create, del-perms, delete, export, import, list

+
+
+
+
+

Sub-commands

+
+
add-perms
+

Add roles permissions

+
airflow roles add-perms [-h] -a [ACTION [ACTION ...]] -r
+                        [RESOURCE [RESOURCE ...]] [-v]
+                        [role [role ...]]
+
+
+
+
Positional Arguments
+
+
role
+

The name of a role

+
+
+
+
+
Named Arguments
+
+
-a, --action
+

The action of permissions

+
+
-r, --resource
+

The name of permissions

+
+
-v, --verbose
+

Make logging output more verbose

+

Default: False

+
+
+
+
+
+
create
+

Create role

+
airflow roles create [-h] [-v] [role [role ...]]
+
+
+
+
Positional Arguments
+
+
role
+

The name of a role

+
+
+
+
+
Named Arguments
+
+
-v, --verbose
+

Make logging output more verbose

+

Default: False

+
+
+
+
+
+
del-perms
+

Delete roles permissions

+
airflow roles del-perms [-h] [-a [ACTION [ACTION ...]]] -r
+                        [RESOURCE [RESOURCE ...]] [-v]
+                        [role [role ...]]
+
+
+
+
Positional Arguments
+
+
role
+

The name of a role

+
+
+
+
+
Named Arguments
+
+
-a, --action
+

The action of permissions

+
+
-r, --resource
+

The name of permissions

+
+
-v, --verbose
+

Make logging output more verbose

+

Default: False

+
+
+
+
+
+
delete
+

Delete role

+
airflow roles delete [-h] [-v] [role [role ...]]
+
+
+
+
Positional Arguments
+
+
role
+

The name of a role

+
+
+
+
+
Named Arguments
+
+
-v, --verbose
+

Make logging output more verbose

+

Default: False

+
+
+
+
+
+
export
+

Export roles (without permissions) from db to JSON file

+
airflow roles export [-h] [-p] [-v] file
+
+
+
+
Positional Arguments
+
+
file
+

Export all roles to JSON file

+
+
+
+
+
Named Arguments
+
+
-p, --pretty
+

Format output JSON file by sorting role names and indenting by 4 spaces

+

Default: False

+
+
-v, --verbose
+

Make logging output more verbose

+

Default: False

+
+
+
+
+
+
import
+

Import roles (without permissions) from JSON file to db

+
airflow roles import [-h] [-v] file
+
+
+
+
Positional Arguments
+
+
file
+

Import roles from JSON file

+
+
+
+
+
Named Arguments
+
+
-v, --verbose
+

Make logging output more verbose

+

Default: False

+
+
+
+
+
+
list
+

List roles

+
airflow roles list [-h] [-o table, json, yaml, plain] [-p] [-v]
+
+
+
+
Named Arguments
+
+
-o, --output
+

Possible choices: table, json, yaml, plain

+

Output format. Allowed values: json, yaml, plain, table (default: table)

+

Default: “table”

+
+
-p, --permission
+

Show role permissions

+

Default: False

+
+
-v, --verbose
+

Make logging output more verbose

+

Default: False

+
+
+
+
+
+
+
+

sync-perm

+

Update permissions for existing roles and optionally DAGs

+
airflow sync-perm [-h] [--include-dags] [-v]
+
+
+
+

Named Arguments

+
+
--include-dags
+

If passed, DAG specific permissions will also be synced.

+

Default: False

+
+
-v, --verbose
+

Make logging output more verbose

+

Default: False

+
+
+
+
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/commits.html b/docs-archive/apache-airflow-providers-fab/1.0.4/commits.html new file mode 100644 index 00000000000..1d3ce61bc9b --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/commits.html @@ -0,0 +1,1165 @@ + + + + + + + + + + + + Package apache-airflow-providers-fab — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

Package apache-airflow-providers-fab

+

Flask App Builder

+

This is detailed commit list of changes for versions provider package: fab. +For high-level changelog, see package information including changelog.

+
+

1.0.4

+

Latest change: 2024-04-15

+ +++++ + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

f8104325b7

2024-04-15

Activate RUF019 that checks for unnecessary key check (#38950)

c3bb80da93

2024-04-12

Remove button for reset my password when we have reset password (#38957)

+
+
+

1.0.3

+

Latest change: 2024-04-10

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

5fa80b6aea

2024-04-10

Prepare docs 1st wave (RC1) April 2024 (#38863)

53cd7173b4

2024-04-10

Fix azure authentication when no email is set (#38872)

6d3d2075ae

2024-04-07

fix: try002 for provider fab (#38801)

e700f4150a

2024-03-30

Rename 'allowed_filter_attrs' to 'allowed_sort_attrs' (#38626)

+
+
+

1.0.2

+

Latest change: 2024-03-25

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

256911aa62

2024-03-25

Prepare fab provider RC1 (#38451)

7776e9154d

2024-03-20

Upgrade FAB to 4.4.1 (#38319)

0a74928894

2024-03-18

Bump ruff to 0.3.3 (#38240)

2e35854a05

2024-03-15

Make the method 'BaseAuthManager.is_authorized_custom_view' abstract (#37915)

c0b849ad2b

2024-03-11

Avoid use of 'assert' outside of the tests (#37718)

c6f34394c4

2024-03-11

Improve suffix handling for provider-generated dependencies (#38029)

3f52790d42

2024-03-06

Resolve G004: Logging statement uses f-string (#37873)

fd4dfd875d

2024-03-06

Remove useless methods from security manager (#37889)

3211a5fcea

2024-03-06

Use 'next' when redirecting (#37904)

89e7f3e7bd

2024-03-05

Add "MENU" permission in auth manager (#37881)

30f7b2abe6

2024-03-04

Avoid to use too broad 'noqa' (#37862)

9b17ff3aa3

2024-02-26

Add post endpoint for dataset events (#37570)

16d2671704

2024-02-20

Add "queuedEvent" endpoint to get/delete DatasetDagRunQueue (#37176)

79603f9302

2024-02-19

Add swagger path to FAB Auth manager and Internal API (#37525)

f2ea8a3e17

2024-02-19

Revoking audit_log permission from all users except admin (#37501)

68e20aa702

2024-02-17

Enable the 'Is Active?' flag by default in user view (#37507)

5a0be392e6

2024-02-16

Add comment about versions updated by release manager (#37488)

4551c592b2

2024-02-14

Until we release 2.9.0, we keep airflow >= 2.9.0.dev0 for FAB provider (#37421)

+
+
+

1.0.1

+

Latest change: 2024-02-14

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

54a400fcb6

2024-02-14

Mark FAB provider as ready (#37362)

ec97a07197

2024-02-13

standardize get_app appbuilder usage (#37397)

28f94f8891

2024-02-10

Move 'IMPORT_ERROR' from DAG related permissions to view related permissions (#37292)

00ed46769e

2024-02-09

D401 support in fab provider (#37283)

e99cfbbd51

2024-02-07

Upgrade to FAB 4.3.11 (#37233)

daa2bceba1

2024-02-07

Use 'next_url' instead of 'next' (#37225)

dec2662190

2024-01-30

feat: Switch all class, functions, methods deprecations to decorators (#36876)

0fce3b6047

2024-01-28

Add "airflow users reset-password" command (#37044)

ce246c0ed8

2024-01-26

fix for role and permission count in export (#36589)

18d2498e44

2024-01-11

Generate doc for fab CLI commands (#36672)

c439ab87c4

2024-01-10

Standardize airflow build process and switch to Hatchling build backend (#36537)

28cad70223

2024-01-03

Move config related to FAB auth manager to FAB provider (#36232)

2093b6f3b9

2024-01-03

Fix security manager inheritance in fab provider (#36538)

dec78ab3f1

2024-01-03

Remove MSSQL support form Airflow core (#36514)

e28627f6a5

2024-01-02

Cli export / import roles including permissions (#36347)

6937ae7647

2023-12-30

Speed up autocompletion of Breeze by simplifying provider state (#36499)

83bdc297ce

2023-12-30

added cli command to list auth managers under 'airflow providers' (#36445)

341d5b747d

2023-12-23

Add feture of "not-ready" provider. (#36391)

+
+
+

1.0.0

+

Latest change: 2023-12-23

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Commit

Committed

Subject

b15d5578da

2023-12-23

Re-apply updated version numbers to 2nd wave of providers in December (#36380)

2be7149598

2023-12-21

fix inheritance checking of security manager in FabAuthManager (#36343)

e9ba37bb58

2023-12-17

Add code snippet formatting in docstrings via Ruff (#36262)

f7f7183617

2023-12-17

Update permission docs (#36120)

4d96a9a3a1

2023-12-13

Remove dependency of 'Connexion' from auth manager interface (#36209)

357355ac09

2023-12-11

Remove 'is_authorized_cluster_activity' from auth manager (#36175)

1eca667e5f

2023-12-11

Create FAB provider and move FAB auth manager in it (#35926)

+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/configurations-ref.html b/docs-archive/apache-airflow-providers-fab/1.0.4/configurations-ref.html new file mode 100644 index 00000000000..dda07453e03 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/configurations-ref.html @@ -0,0 +1,921 @@ + + + + + + + + + + + + Configuration Reference — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+
+
+

Configuration Reference

+

This page contains the list of all available Airflow configurations for the +apache-airflow-providers-fab provider that can be set in the airflow.cfg file or using environment variables.

+
+

Note

+

The configuration embedded in provider packages started to be used as of Airflow 2.7.0. Previously the +configuration was described and configured in the Airflow core package - so if you are using Airflow +below 2.7.0, look at Airflow documentation for the list of available configuration options +that were available in Airflow core.

+
+
+

Note

+

For more information see Setting Configuration Options.

+
+
+
+
+

Sections:

+ +
+
+

[fab]

+

This section contains configs specific to FAB provider.

+
+

auth_rate_limited

+
+
+

New in version 1.0.0.

+
+
+

Boolean for enabling rate limiting on authentication endpoints.

+
+
Type
+

boolean

+
+
Default
+

True

+
+
Environment Variable
+

AIRFLOW__FAB__AUTH_RATE_LIMITED

+
+
+
+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/genindex.html b/docs-archive/apache-airflow-providers-fab/1.0.4/genindex.html new file mode 100644 index 00000000000..69011a3ad76 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/genindex.html @@ -0,0 +1,2190 @@ + + + + + + + + + + + + Index — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ + +

Index

+ +
+ _ + | A + | B + | C + | D + | E + | F + | G + | I + | J + | L + | M + | N + | O + | P + | R + | S + | T + | U + | V + +
+

_

+ + + +
+ +

A

+ + + +
+ +

B

+ + + +
+ +

C

+ + + +
+ +

D

+ + + +
+ +

E

+ + + +
+ +

F

+ + + +
+ +

G

+ + + +
+ +

I

+ + + +
+ +

J

+ + +
+ +

L

+ + + +
+ +

M

+ + + +
+ +

N

+ + +
+ +

O

+ + + +
+ +

P

+ + + +
+ +

R

+ + + +
+ +

S

+ + + +
+ +

T

+ + +
+ +

U

+ + + +
+ +

V

+ + +
+ + + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/index.html b/docs-archive/apache-airflow-providers-fab/1.0.4/index.html new file mode 100644 index 00000000000..16540c551c3 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/index.html @@ -0,0 +1,928 @@ + + + + + + + + + + + + apache-airflow-providers-fab — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+

apache-airflow-providers-fab

+
+
+
+
+
+
+
+
+
+
+
+
+
+

apache-airflow-providers-fab package

+

Flask App Builder

+

Release: 1.0.4

+
+
+

Provider package

+

This package is for the fab provider. +All classes for this package are included in the airflow.providers.fab python package.

+
+
+

Installation

+

You can install this package on top of an existing Airflow 2 installation via +pip install apache-airflow-providers-fab. +For the minimum Airflow version supported, see Requirements below.

+
+
+

Requirements

+

The minimum Apache Airflow version supported by this provider package is 2.9.0.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + +

PIP package

Version required

apache-airflow

>=2.9.0

flask

>=2.2,<2.3

flask-appbuilder

==4.4.1

flask-login

>=0.6.2

google-re2

>=1.0

+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/installing-providers-from-sources.html b/docs-archive/apache-airflow-providers-fab/1.0.4/installing-providers-from-sources.html new file mode 100644 index 00000000000..563d421a117 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/installing-providers-from-sources.html @@ -0,0 +1,974 @@ + + + + + + + + + + + + Installing from sources — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+
+
+

Installing from sources

+
+

Released packages

+

This page describes downloading and verifying apache-airflow-providers-fab provider version +1.0.4 using officially released packages. +You can also install the provider package - as most Python packages - via +PyPI . +You can choose different version of the provider by selecting different version from the drop-down at +the top-left of the page.

+

The sdist and whl packages released are the “official” sources of installation that you can use if +you want to verify the origin of the packages and want to verify checksums and signatures of the packages. +The packages are available via the +Official Apache Software Foundations Downloads

+

The downloads are available at:

+ +

If you want to install from the source code, you can download from the sources link above, it will contain +a INSTALL file containing details on how you can build and install the provider.

+
+
+

Release integrity

+

PGP signatures KEYS

+

It is essential that you verify the integrity of the downloaded files using the PGP or SHA signatures. +The PGP signatures can be verified using GPG or PGP. Please download the KEYS as well as the asc +signature files for relevant distribution. It is recommended to get these files from the +main distribution directory and not from the mirrors.

+
gpg -i KEYS
+
+
+

or

+
pgpk -a KEYS
+
+
+

or

+
pgp -ka KEYS
+
+
+

To verify the binaries/sources you can download the relevant asc files for it from main +distribution directory and follow the below guide.

+
gpg --verify apache-airflow-providers-********.asc apache-airflow-*********
+
+
+

or

+
pgpv apache-airflow-providers-********.asc
+
+
+

or

+
pgp apache-airflow-providers-********.asc
+
+
+

Example:

+
$ gpg --verify apache-airflow-providers-fab-1.0.4.tar.gz.asc apache-airflow-providers-fab-1.0.4.tar.gz
+  gpg: Signature made Sat 11 Sep 12:49:54 2021 BST
+  gpg:                using RSA key CDE15C6E4D3A8EC4ECF4BA4B6674E08AD7DE406F
+  gpg:                issuer "kaxilnaik@apache.org"
+  gpg: Good signature from "Kaxil Naik <kaxilnaik@apache.org>" [unknown]
+  gpg:                 aka "Kaxil Naik <kaxilnaik@gmail.com>" [unknown]
+  gpg: WARNING: The key's User ID is not certified with a trusted signature!
+  gpg:          There is no indication that the signature belongs to the owner.
+  Primary key fingerprint: CDE1 5C6E 4D3A 8EC4 ECF4  BA4B 6674 E08A D7DE 406F
+
+
+

The “Good signature from …” is indication that the signatures are correct. +Do not worry about the “not certified with a trusted signature” warning. Most of the certificates used +by release managers are self signed, that’s why you get this warning. By importing the server in the +previous step and importing it via ID from KEYS page, you know that this is a valid Key already.

+

For SHA512 sum check, download the relevant sha512 and run the following:

+
shasum -a 512 apache-airflow-providers-********  | diff - apache-airflow-providers-********.sha512
+
+
+

The SHASUM of the file should match the one provided in .sha512 file.

+

Example:

+
shasum -a 512 apache-airflow-providers-fab-1.0.4.tar.gz  | diff - apache-airflow-providers-fab-1.0.4.tar.gz.sha512
+
+
+
+
+

Verifying PyPI releases

+

You can verify the Provider .whl packages from PyPI by locally downloading the package and signature +and SHA sum files with the script below:

+
#!/bin/bash
+PACKAGE_VERSION=1.0.4
+PACKAGE_NAME=apache-airflow-providers-fab
+provider_download_dir=$(mktemp -d)
+pip download --no-deps "${PACKAGE_NAME}==${PACKAGE_VERSION}" --dest "${provider_download_dir}"
+curl "https://downloads.apache.org/airflow/providers/apache_airflow_providers_fab-1.0.4-py3-none-any.whl.asc" \
+    -L -o "${provider_download_dir}/apache_airflow_providers_fab-1.0.4-py3-none-any.whl.asc"
+curl "https://downloads.apache.org/airflow/providers/apache_airflow_providers_fab-1.0.4-py3-none-any.whl.sha512" \
+    -L -o "${provider_download_dir}/apache_airflow_providers_fab-1.0.4-py3-none-any.whl.sha512"
+echo
+echo "Please verify files downloaded to ${provider_download_dir}"
+ls -la "${provider_download_dir}"
+echo
+
+
+

Once you verify the files following the instructions from previous chapter you can remove the temporary +folder created.

+
+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/objects.inv b/docs-archive/apache-airflow-providers-fab/1.0.4/objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..2b4d281b923068ad7f3affc77753bba390627857 GIT binary patch literal 4583 zcmVNERX>N99Zgg*Qc_4OWa&u{KZXhxWBOp+6Z)#;@bUGkmaA9L; zWi4T8a%OCAcP(&oZ+2;9WpZ;ZW?^CqBOq2~a&u{KZaN?_E-)@M3L_v?Xk{RBWo=<; zZe(S0Aa78b#rNMXCQiPX<{x4c-q~aTXW(# z8iw!r6;#b$>|Q|6-p(DJ(7jZJkcDJswzjrZ!WN*3u{@HUH1q3M2Olw{K^ARE7c(6j z`}6baeE1|mOg9mEA19Q&;SfIB-CFV zbNgB!6pwZJsJx;5WpShX=f`UpyrMYlhLIaFhr|D6H~`%Ps35EC-2`%c_b{72K7+~2 z^S>_36FRsCIG?SilMeJd8rHz%uIL0ZbN~{N^=+6vO#N-tZUK~Kl zY9;q8qH9D6GgtsLOd2c$8g@+=181Sl&~CUzquK1ny!FgxdC*2=>j32kg@Og-fZIt3 zj#H*v1XLC}<@n0Xn34zq$g@p?=pHlK3NC&%K>3mRA0c5Jq6no3h-dT*1r0&wm26R3 zyU#pO<4L552V9Si1g62xhX_dsb0uMkhKk9uwqegy;o2}-l&0O9SeGChU=>-@DNtrT zsVXI$2vk`PSVI~_7zAX`FGIbyU)_Ly)~;LOd3huHA9?e*8&PG;INW%${0i=t)5-G` zEEf+`jkf#+s0J9P^U3VNZaT1ddY&yFC-!1~nJrh(kCVB*(L8&+dw98@g8RwWm9>x$ z6U#&KVYYgf+1cJOe44CQzb%&c_5x0q^Vw>}Gqk;dXmyEgclr}_U~(r4Y!?{8a{BL= z*>ZYsH|+HHr^WKw1xD~?ZaL>{Zhu%Vr>n)w^3L8u=w&rsT3uBafc7^Y1*z>BTrygo zaX2GbP9E_%*-kK1flwW@wnA zZc<(_07EretUH=_5waoHfFhV82S7s(nMZp~1D)=iFI_{A#Np*<9=K?E7o4asw;1{ufv zKO6~Cn5Go3GhU=xOuNC9r7_$iXNYm=3@T5mZiQ{>5#j``xNm>(igtD3*U_bSax*}R z_T&xO%_uJ@V#1Y-m;djCh9+v(oAR3Mrra3RT+{!?pyrzXHwHD=^uIBvsiyypG1YTj z9OQ0Co8riTbBr`&s{Jf%N&hUEBvI~64%QitLT$&Qk6|yQ3{gNRObOKsu;o803cWQG-8uLT(0TRgu@U{qIkq(Z0@o9MJ+J7l?Tvl}XND@z z^~Y;AP`V?beV{G>LQ6TN8+DqZ5QK0Gu-&j3jR4QWICcP%WU1|xvaP`FY_Mv3Sj(C_ z4cp8ILd=o~9zfA=w-HuM0$R(a*6|UF|Kf#FK;jMFX0%)^=mc_%0*81rmXbYq!|2@& zU|vDF0-8dG9LZ@3A(0!TZ;)cRwzsM}qP06;@fOOKQ`*~bl3J2+W6ISEmbO45=uPM3YZ}=uFla zV$q*HGz8FP!m2C6EEHQyqz8?`ovxpLD%TKL|>TRkg&<`+mVSIM4jBBjFL!KC(vj8 z+rY6S#Y!I~djh5I+|fG>l^1GoO^j9``>1x1?W~~c>WkGKrmB;Ed@xZ4E;4Q)#n+gs`b8#O92s+_^>A#>zkw6Q67bTvdEFf(l52Q^wIl(r=qZ=2I+gi zRY4RxWb~CZJFR;)LeTg4saT~dU*;`50M~%#gS)CaDd>RMop?*Nca1kqX%}2k;8&j5 znqEguOP!sNn&!rn;4l`MdhL?xaiRwG_uj%;Ag!60;QQ9_G^mE6v>kaXkHfwtAjD>hF1b8LuuVc|(-) zhs^|KVa;Gj7AB?NuzG)$Ka;x8x7wr9>2`KIlz-aKIu`uSsOz4(2HIng((6N-eW)1pgrMwq?Zng-^A{5UdR#$QNeKU$JmNglVs}% z2foM=JNhRHj<@~@lE-wxnv1*ZveH9>e9=)3j+d_guB%epDX-n0$|!}1)`BNeNO`P; z2U;{2lG&%EzHN>-*}t(DP%%5}r!w%z9aN)nC$2U*oO%6!l{cJ3fI0U z5e)=iw8$2MH)3$;ixgENi=xa2MdG-(6vv>;(lmRtM6arY?Y=W=0OP{PmJwcKhH&e+ zpdAWc%R?RX&!VwLPlR|Bl`Bu()gg8lkS#OEb;!Mk01VtuS-BE1Fb%{i#1KX#Mm}h2 z)i$mR5(oXU1O<45>#M2#(6;tL#UJl!r(Y493!>3zM@Nc^5!$}>w~Iu-Z8iCLH5~* zRT}=3Yf6s$DK7S45urRKUJgQGaSBe zppNnd8I7D5Chc-2KvBT^em_M(B{z8;3k z0@`6eqVj;0^#M5U+FnW#JHO=vAASgOzb}eooVwoz$PbTEi(Q@HdyA_P?HDg=%_GkT zm%UWg=1t#H3WLUcqRVhGdy*eT`s6GQJi-clAtoAZT%{wbc;NJvnOLvM=b+Wz(E zn@C|i>i`lXKq%M~iah8x*CcvzN<^i{o0B5sswkfFf+!2Ua8XSt+Td>}%qKaV)>66( zij>B@kfKI7eJBhXihL*v>Vo{(XP~agn-aS&%A1V`8lwEzfIxJ--|BOqYVy$eSpR$YpwBUAXIO!quKczB#aYveQzQgw=K{o;Vrjnw;+zvK2KIt@UogN!D_l%%@&Ut9qBM%R3JeB4pfgQ!_C2sEC^S@pTd)4%39Ac!DiS47o^e5SzUaq1~f zRZm1Gll~aYHDs->xxKV9s_WB0#TsmTkwrVsg@h2nHHtt$qHJ$_DiA(|E(EFS<+_zz zDapi!wY*fYo0ILxyNzk!sr>tizi(kZbq3JZ`sy66-SyTvY6t4CbLh6#W9N7+uFuXQ zi+asHVuuoi3pMgNc3W%abG)|J(93*6(!#pAg=TB5+y=F~K5p|mP!qSIZLNdbq!!n{ zCtxkD#oDAU)L(6CTWhX1sZDj3+9avmEJ1G+wldOn5Vo>3zROrj_Dg=lKplFT&>))O zs_FK;H>jF!4}FW0$pCffLZg>`#Oqx%jH-mz4ql_ZRqc&JvN;Q%;cR8w)o(!~;k2!nv^`DMsHg=izrdg5WFFYiNx7fY*K8CO>H zWSP;TFF=o4rr`X_kc75Ly$Gq>(Gyo~n`Ktv8M}HiTgLRX%8Y4NX4|Bm!nz$zaVd^W z<*=G9O*z8A#X3S15DHVmf9uxdIcex(1=ZWvHGpbgH9@WmeK9Y;0U9^7sZU$FnEm+m zixp@CU&VJZj@%}NC%Kr!hds#{sOAB6AU`m7anLFoU}*apBT`Q6Xfy1x)6PI+R~sE6 z$D85|FCG3HbX@eI4|{t3$WUjM%b=Ujy}pK%-upw1^#%i7{}p|9jmoMTFdlT8{^aa|M39$P-CqABL&wmeve`xC`RQ-j67w0#A~0Fr``G|K6p%7pQr=M z@6^2`vk4xF8z@e30OgTVXHB;r&CNf}hLgtq<|kTV(*9K$`Vv9*I-DfQ=L|x4x7IYf*p*vNbKBJGhE(OFW(iH1K!IU zQM741t8V2oC!dFR4>KMg`G||?65^CKUQoBx3r{e3<@iIGz+i_)d14uriDe`b3y<*) z-u}Y>ly>9_S!GGw&!|+wN{XMzx;pys~G^Q$3eyBy2SzHSK5@}I}#Q~g@u;Q zLEB6-2u^-PB;)G-aEUgEqBuZpAhGFvgp{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative}details.sd-dropdown .sd-summary-title{font-weight:700;padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary{list-style:none;padding:1em}details.sd-dropdown summary .sd-octicon.no-title{vertical-align:middle}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown summary::-webkit-details-marker{display:none}details.sd-dropdown summary:focus{outline:none}details.sd-dropdown .sd-summary-icon{margin-right:.5em}details.sd-dropdown .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary:hover .sd-summary-up svg,details.sd-dropdown summary:hover .sd-summary-down svg{opacity:1;transform:scale(1.1)}details.sd-dropdown .sd-summary-up svg,details.sd-dropdown .sd-summary-down svg{display:block;opacity:.6}details.sd-dropdown .sd-summary-up,details.sd-dropdown .sd-summary-down{pointer-events:none;position:absolute;right:1em;top:1em}details.sd-dropdown[open]>.sd-summary-title .sd-summary-down{visibility:hidden}details.sd-dropdown:not([open])>.sd-summary-title .sd-summary-up{visibility:hidden}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #0071bc;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0060a0;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem} diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/output-spelling-results-apache-airflow-providers-fab/_sphinx_design_static/design-tabs.js b/docs-archive/apache-airflow-providers-fab/1.0.4/output-spelling-results-apache-airflow-providers-fab/_sphinx_design_static/design-tabs.js new file mode 100644 index 00000000000..36b38cf0d91 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/output-spelling-results-apache-airflow-providers-fab/_sphinx_design_static/design-tabs.js @@ -0,0 +1,27 @@ +var sd_labels_by_text = {}; + +function ready() { + const li = document.getElementsByClassName("sd-tab-label"); + for (const label of li) { + syncId = label.getAttribute("data-sync-id"); + if (syncId) { + label.onclick = onLabelClick; + if (!sd_labels_by_text[syncId]) { + sd_labels_by_text[syncId] = []; + } + sd_labels_by_text[syncId].push(label); + } + } +} + +function onLabelClick() { + // Activate other inputs with the same sync id. + syncId = this.getAttribute("data-sync-id"); + for (label of sd_labels_by_text[syncId]) { + if (label === this) continue; + label.previousElementSibling.checked = true; + } + window.localStorage.setItem("sphinx-design-last-tab", syncId); +} + +document.addEventListener("DOMContentLoaded", ready, false); diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/py-modindex.html b/docs-archive/apache-airflow-providers-fab/1.0.4/py-modindex.html new file mode 100644 index 00000000000..828e5190c1e --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/py-modindex.html @@ -0,0 +1,1010 @@ + + + + + + + + + + + + Python Module Index — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ + +

Python Module Index

+ +
+ a +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
+ a
+ airflow +
    + airflow.providers.fab +
    + airflow.providers.fab.auth_manager +
    + airflow.providers.fab.auth_manager.api +
    + airflow.providers.fab.auth_manager.api.auth +
    + airflow.providers.fab.auth_manager.api.auth.backend +
    + airflow.providers.fab.auth_manager.api.auth.backend.basic_auth +
    + airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth +
    + airflow.providers.fab.auth_manager.api_endpoints +
    + airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint +
    + airflow.providers.fab.auth_manager.api_endpoints.user_endpoint +
    + airflow.providers.fab.auth_manager.cli_commands +
    + airflow.providers.fab.auth_manager.cli_commands.definition +
    + airflow.providers.fab.auth_manager.cli_commands.role_command +
    + airflow.providers.fab.auth_manager.cli_commands.sync_perm_command +
    + airflow.providers.fab.auth_manager.cli_commands.user_command +
    + airflow.providers.fab.auth_manager.cli_commands.utils +
    + airflow.providers.fab.auth_manager.decorators +
    + airflow.providers.fab.auth_manager.decorators.auth +
    + airflow.providers.fab.auth_manager.fab_auth_manager +
    + airflow.providers.fab.auth_manager.models +
    + airflow.providers.fab.auth_manager.models.anonymous_user +
    + airflow.providers.fab.auth_manager.openapi +
    + airflow.providers.fab.auth_manager.security_manager +
    + airflow.providers.fab.auth_manager.security_manager.constants +
    + airflow.providers.fab.auth_manager.security_manager.override +
    + airflow.providers.fab.auth_manager.views +
    + airflow.providers.fab.auth_manager.views.permissions +
    + airflow.providers.fab.auth_manager.views.roles_list +
    + airflow.providers.fab.auth_manager.views.user +
    + airflow.providers.fab.auth_manager.views.user_edit +
    + airflow.providers.fab.auth_manager.views.user_stats +
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/search.html b/docs-archive/apache-airflow-providers-fab/1.0.4/search.html new file mode 100644 index 00000000000..199b35a2107 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/search.html @@ -0,0 +1,887 @@ + + + + + + + + + + + + Search — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +

Search

+ + + + +

+ Searching for multiple words only shows matches that contain + all words. +

+ + +
+ + + +
+ + + +
+ +
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/searchindex.js b/docs-archive/apache-airflow-providers-fab/1.0.4/searchindex.js new file mode 100644 index 00000000000..b38e59e0be3 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"docnames": ["_api/airflow/providers/fab/auth_manager/api/auth/backend/basic_auth/index", "_api/airflow/providers/fab/auth_manager/api/auth/backend/index", "_api/airflow/providers/fab/auth_manager/api/auth/backend/kerberos_auth/index", "_api/airflow/providers/fab/auth_manager/api/auth/index", "_api/airflow/providers/fab/auth_manager/api/index", "_api/airflow/providers/fab/auth_manager/api_endpoints/index", "_api/airflow/providers/fab/auth_manager/api_endpoints/role_and_permission_endpoint/index", "_api/airflow/providers/fab/auth_manager/api_endpoints/user_endpoint/index", "_api/airflow/providers/fab/auth_manager/cli_commands/definition/index", "_api/airflow/providers/fab/auth_manager/cli_commands/index", "_api/airflow/providers/fab/auth_manager/cli_commands/role_command/index", "_api/airflow/providers/fab/auth_manager/cli_commands/sync_perm_command/index", "_api/airflow/providers/fab/auth_manager/cli_commands/user_command/index", "_api/airflow/providers/fab/auth_manager/cli_commands/utils/index", "_api/airflow/providers/fab/auth_manager/decorators/auth/index", "_api/airflow/providers/fab/auth_manager/decorators/index", "_api/airflow/providers/fab/auth_manager/fab_auth_manager/index", "_api/airflow/providers/fab/auth_manager/index", "_api/airflow/providers/fab/auth_manager/models/anonymous_user/index", "_api/airflow/providers/fab/auth_manager/models/index", "_api/airflow/providers/fab/auth_manager/openapi/index", "_api/airflow/providers/fab/auth_manager/security_manager/constants/index", "_api/airflow/providers/fab/auth_manager/security_manager/index", "_api/airflow/providers/fab/auth_manager/security_manager/override/index", "_api/airflow/providers/fab/auth_manager/views/index", "_api/airflow/providers/fab/auth_manager/views/permissions/index", "_api/airflow/providers/fab/auth_manager/views/roles_list/index", "_api/airflow/providers/fab/auth_manager/views/user/index", "_api/airflow/providers/fab/auth_manager/views/user_edit/index", "_api/airflow/providers/fab/auth_manager/views/user_stats/index", "_api/airflow/providers/fab/index", "auth-manager/access-control", "auth-manager/api-authentication", "auth-manager/index", "auth-manager/webserver-authentication", "changelog", "cli-ref", "commits", "configurations-ref", "index", "installing-providers-from-sources", "security", "stable-rest-api-ref"], "filenames": ["_api/airflow/providers/fab/auth_manager/api/auth/backend/basic_auth/index.rst", "_api/airflow/providers/fab/auth_manager/api/auth/backend/index.rst", "_api/airflow/providers/fab/auth_manager/api/auth/backend/kerberos_auth/index.rst", "_api/airflow/providers/fab/auth_manager/api/auth/index.rst", "_api/airflow/providers/fab/auth_manager/api/index.rst", "_api/airflow/providers/fab/auth_manager/api_endpoints/index.rst", "_api/airflow/providers/fab/auth_manager/api_endpoints/role_and_permission_endpoint/index.rst", "_api/airflow/providers/fab/auth_manager/api_endpoints/user_endpoint/index.rst", "_api/airflow/providers/fab/auth_manager/cli_commands/definition/index.rst", "_api/airflow/providers/fab/auth_manager/cli_commands/index.rst", "_api/airflow/providers/fab/auth_manager/cli_commands/role_command/index.rst", "_api/airflow/providers/fab/auth_manager/cli_commands/sync_perm_command/index.rst", "_api/airflow/providers/fab/auth_manager/cli_commands/user_command/index.rst", "_api/airflow/providers/fab/auth_manager/cli_commands/utils/index.rst", "_api/airflow/providers/fab/auth_manager/decorators/auth/index.rst", "_api/airflow/providers/fab/auth_manager/decorators/index.rst", "_api/airflow/providers/fab/auth_manager/fab_auth_manager/index.rst", "_api/airflow/providers/fab/auth_manager/index.rst", "_api/airflow/providers/fab/auth_manager/models/anonymous_user/index.rst", "_api/airflow/providers/fab/auth_manager/models/index.rst", "_api/airflow/providers/fab/auth_manager/openapi/index.rst", "_api/airflow/providers/fab/auth_manager/security_manager/constants/index.rst", "_api/airflow/providers/fab/auth_manager/security_manager/index.rst", "_api/airflow/providers/fab/auth_manager/security_manager/override/index.rst", "_api/airflow/providers/fab/auth_manager/views/index.rst", "_api/airflow/providers/fab/auth_manager/views/permissions/index.rst", "_api/airflow/providers/fab/auth_manager/views/roles_list/index.rst", "_api/airflow/providers/fab/auth_manager/views/user/index.rst", "_api/airflow/providers/fab/auth_manager/views/user_edit/index.rst", "_api/airflow/providers/fab/auth_manager/views/user_stats/index.rst", "_api/airflow/providers/fab/index.rst", "auth-manager/access-control.rst", "auth-manager/api-authentication.rst", "auth-manager/index.rst", "auth-manager/webserver-authentication.rst", "changelog.rst", "cli-ref.rst", "commits.rst", "configurations-ref.rst", "index.rst", "installing-providers-from-sources.rst", "security.rst", "stable-rest-api-ref.rst"], "titles": ["airflow.providers.fab.auth_manager.api.auth.backend.basic_auth", "airflow.providers.fab.auth_manager.api.auth.backend", "airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth", "airflow.providers.fab.auth_manager.api.auth", "airflow.providers.fab.auth_manager.api", "airflow.providers.fab.auth_manager.api_endpoints", "airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint", "airflow.providers.fab.auth_manager.api_endpoints.user_endpoint", "airflow.providers.fab.auth_manager.cli_commands.definition", "airflow.providers.fab.auth_manager.cli_commands", "airflow.providers.fab.auth_manager.cli_commands.role_command", "airflow.providers.fab.auth_manager.cli_commands.sync_perm_command", "airflow.providers.fab.auth_manager.cli_commands.user_command", "airflow.providers.fab.auth_manager.cli_commands.utils", "airflow.providers.fab.auth_manager.decorators.auth", "airflow.providers.fab.auth_manager.decorators", "airflow.providers.fab.auth_manager.fab_auth_manager", "airflow.providers.fab.auth_manager", "airflow.providers.fab.auth_manager.models.anonymous_user", "airflow.providers.fab.auth_manager.models", "airflow.providers.fab.auth_manager.openapi", "airflow.providers.fab.auth_manager.security_manager.constants", "airflow.providers.fab.auth_manager.security_manager", "airflow.providers.fab.auth_manager.security_manager.override", "airflow.providers.fab.auth_manager.views", "airflow.providers.fab.auth_manager.views.permissions", "airflow.providers.fab.auth_manager.views.roles_list", "airflow.providers.fab.auth_manager.views.user", "airflow.providers.fab.auth_manager.views.user_edit", "airflow.providers.fab.auth_manager.views.user_stats", "airflow.providers.fab", "Access Control", "API Authentication", "Flask AppBuilder (FAB) auth manager", "Webserver authentication", "Changelog", "FAB CLI Commands", "Package apache-airflow-providers-fab", "Configuration Reference", "apache-airflow-providers-fab", "Installing from sources", "Releasing security patches", "REST API Reference"], "terms": {"basic": 0, "authent": [0, 23, 33, 35, 37, 38], "client_auth": [0, 2, 32], "tupl": [0, 2, 23, 32], "str": [0, 2, 16, 23, 32, 34], "ani": [0, 2, 23, 31, 34, 40], "none": [0, 2, 6, 7, 12, 16, 23, 31, 32, 34, 40], "sourc": [0, 2, 6, 7, 8, 10, 11, 12, 13, 14, 16, 18, 19, 21, 23, 25, 26, 27, 28, 29, 30, 31, 36], "t": [0, 14, 23, 31], "init_app": [0, 2, 32], "_": 0, "initi": [0, 16, 23, 35], "auth_current_us": 0, "set": [0, 23, 31, 32, 34, 35, 37, 38], "current": [0, 16, 23, 32], "user": [0, 7, 12, 16, 17, 18, 19, 23, 24, 30, 32, 33, 34, 37, 40], "author": [0, 16, 32, 33], "header": [0, 32], "exist": [0, 10, 11, 23, 31, 32, 36, 39], "requires_authent": [0, 2, 32], "decor": [0, 17, 30, 32, 37], "requir": [0, 31, 34, 36, 41], "1": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 38, 39, 40, 41, 42], "0": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 38, 39, 40, 41, 42], "4": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 38, 39, 40, 41, 42], "2": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 38, 39, 40, 41, 42], "10": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42], "dev0": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42], "thi": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42], "i": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42], "an": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42], "experiment": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42], "featur": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42], "basic_auth": [1, 3, 4, 32], "kerberos_auth": [1, 3, 4, 32], "log": [2, 14, 16, 18, 23, 31, 34, 36, 37], "find_us": [2, 23], "usernam": [2, 7, 12, 19, 23, 31, 32, 34, 36], "email": [2, 12, 19, 23, 34, 35, 36, 37], "backend": [3, 4, 17, 23, 32, 33, 37], "auth": [4, 15, 16, 17, 18, 19, 23, 30, 32, 34, 37], "role_and_permission_endpoint": [5, 17, 30], "user_endpoint": [5, 17, 30], "get_rol": 6, "role_nam": [6, 23, 31], "get": [6, 7, 16, 23, 31, 32, 34, 37, 40, 41], "role": [6, 10, 11, 12, 18, 19, 23, 34, 37], "order_bi": [6, 7], "name": [6, 16, 19, 23, 25, 26, 27, 28, 29, 31, 32, 34], "limit": [6, 7, 23, 31, 34, 38], "offset": [6, 7], "get_permiss": [6, 23], "permiss": [6, 10, 11, 16, 17, 19, 23, 24, 26, 27, 28, 29, 30, 34, 36, 37], "delete_rol": [6, 23], "delet": [6, 7, 10, 12, 23, 31, 37], "patch_rol": 6, "update_mask": [6, 7], "updat": [6, 7, 11, 23, 31, 34, 36, 37], "post_rol": 6, "creat": [6, 7, 10, 12, 23, 31, 32, 34, 37, 40], "new": [6, 7, 10, 12, 23, 27, 31, 32, 38, 41], "get_us": [7, 16], "id": [7, 12, 19, 23, 31, 34, 40], "post_us": 7, "patch_us": 7, "delete_us": 7, "arg_usernam": 8, "arg_username_opt": 8, "arg_firstnam": 8, "arg_lastnam": 8, "arg_rol": 8, "arg_email": 8, "arg_email_opt": 8, "arg_password": 8, "arg_use_random_password": 8, "arg_user_import": 8, "arg_user_export": 8, "arg_create_rol": 8, "arg_list_rol": 8, "arg_permiss": 8, "arg_role_resourc": 8, "arg_role_act": 8, "arg_role_action_requir": 8, "arg_role_import": 8, "arg_role_export": 8, "arg_role_export_fmt": 8, "arg_include_dag": 8, "users_command": 8, "roles_command": 8, "sync_perm_command": [8, 9, 17, 30], "definit": [9, 16, 17, 30], "role_command": [9, 17, 30], "user_command": [9, 17, 30], "util": [9, 17, 30], "sub": [10, 12, 16], "command": [10, 11, 12, 16, 31, 32, 34, 37], "roles_list": [10, 17, 24, 30], "arg": [10, 11, 12, 31], "list": [10, 12, 23, 31, 34, 37, 38], "all": [10, 12, 16, 23, 31, 32, 33, 36, 37, 38, 39, 41], "roles_cr": 10, "empti": 10, "db": [10, 12, 23, 31, 32, 34, 36], "roles_delet": 10, "roles_add_perm": 10, "add": [10, 23, 31, 32, 34, 37], "roles_del_perm": 10, "from": [10, 12, 23, 31, 34, 36, 37, 41], "roles_export": 10, "export": [10, 12, 37], "databas": [10, 23, 33], "file": [10, 12, 23, 32, 34, 36, 38, 40, 42], "includ": [10, 16, 31, 34, 36, 37, 39, 41], "roles_import": 10, "import": [10, 12, 34, 37, 40], "given": [10, 16, 23, 31, 34], "json": [10, 12, 34, 36], "note": [10, 23, 32, 34], "alreadi": [10, 23, 34, 40], "overwritten": 10, "even": [10, 32], "when": [10, 16, 18, 31, 32, 35, 37, 41], "chang": [10, 23, 31, 32, 37, 41], "sync": [11, 23], "sync_perm": 11, "dag": [11, 16, 19, 23, 36, 37], "userschema": 12, "onli": [12, 16, 23, 31, 32, 34, 41], "exclud": 12, "mani": 12, "fals": [12, 23, 36], "context": 12, "load_onli": 12, "dump_onli": 12, "partial": 12, "unknown": [12, 40], "base": [12, 16, 18, 19, 23, 25, 26, 27, 28, 29], "marshmallow": 12, "schema": [12, 33], "collect": [12, 23], "item": 12, "firstnam": [12, 34, 36], "lastnam": [12, 34, 36], "users_list": 12, "line": [12, 34], "users_cr": 12, "user_reset_password": 12, "reset": [12, 23, 31, 35, 37], "password": [12, 19, 23, 31, 32, 35, 37], "users_delet": 12, "users_manage_rol": 12, "remov": [12, 23, 31, 34, 35, 37, 40], "append": [12, 23], "users_export": 12, "users_import": 12, "add_rol": [12, 23], "remove_rol": 12, "get_application_build": 13, "fabauthmanag": [16, 23, 37], "appbuild": [16, 23, 31, 34, 37, 39], "manag": [16, 18, 19, 23, 32, 34, 36, 37, 40], "base_auth_manag": 16, "baseauthmanag": [16, 37], "flask": [16, 23, 31, 32, 34, 37, 39], "respons": [16, 23], "backward": 16, "compat": 16, "experi": 16, "static": [16, 23], "get_cli_command": 16, "vend": 16, "cli": [16, 31, 32, 34, 37], "get_api_endpoint": 16, "return": [16, 19, 23, 27, 34], "api": [16, 17, 23, 30, 31, 33, 34, 37], "endpoint": [16, 31, 34, 37, 38], "": [16, 23, 25, 26, 27, 28, 29, 34, 36, 40, 42], "get_user_display_nam": 16, "displai": 16, "associ": [16, 23, 31, 34], "session": [16, 23, 32], "init": [16, 23], "run": [16, 31, 36, 40], "oper": [16, 23], "is_logged_in": 16, "whether": 16, "is_authorized_configur": 16, "method": [16, 23, 27, 31, 32, 37], "detail": [16, 31, 32, 34, 37, 40], "perform": 16, "action": [16, 19, 23, 25, 27, 31, 36], "configur": [16, 23, 31, 32, 34], "paramet": [16, 23, 36], "resourcemethod": 16, "model": [16, 17, 23, 30, 31, 41], "resource_detail": 16, "configurationdetail": 16, "option": [16, 32, 34, 36, 38], "about": [16, 23, 37, 40, 41], "base_us": [16, 18, 19], "baseus": [16, 18, 19], "If": [16, 23, 32, 34, 36, 40], "us": [16, 18, 23, 31, 32, 33, 36, 37, 38, 40, 41], "is_authorized_connect": 16, "connect": [16, 31], "connectiondetail": 16, "is_authorized_dag": 16, "access_ent": 16, "access": [16, 23, 32, 33], "There": [16, 23, 31, 34, 40], "ar": [16, 23, 31, 32, 34, 36, 38, 39, 40, 41], "multipl": [16, 31, 32, 34], "scenario": 16, "dag_access": 16, "which": [16, 19, 23, 31, 32, 41], "mean": [16, 31, 32], "want": [16, 23, 32, 34, 40, 41], "itself": [16, 31, 34, 41], "entiti": [16, 33], "e": [16, 23, 31, 34, 36], "g": [16, 23, 31, 34], "check": [16, 23, 32, 34, 37, 40], "ha": [16, 19, 23, 31], "read": [16, 23, 31, 34], "els": 16, "edit": [16, 23, 31, 34], "howev": [16, 31, 34], "specif": [16, 23, 31, 34, 36, 38], "target": 16, "just": 16, "The": [16, 23, 31, 32, 33, 34, 36, 38, 39, 40, 41], "dagaccessent": 16, "dagdetail": 16, "is_authorized_dataset": 16, "dataset": [16, 31, 37], "datasetdetail": 16, "is_authorized_pool": 16, "pool": [16, 31, 32], "pooldetail": 16, "is_authorized_vari": 16, "variabl": [16, 31, 34, 38], "variabledetail": 16, "is_authorized_view": 16, "access_view": 16, "state": [16, 37], "instal": [16, 34, 41], "accessview": 16, "view": [16, 17, 23, 30, 31, 32, 37], "request": [16, 23, 27, 32], "is_authorized_custom_view": [16, 37], "resource_nam": [16, 23], "custom": [16, 23, 25, 26, 27, 28, 29, 34], "A": [16, 23, 34], "can": [16, 19, 23, 31, 32, 34, 38, 39, 40, 41], "defin": [16, 23, 31, 32, 33, 34], "part": [16, 36], "avail": [16, 34, 36, 38, 40], "environ": [16, 34, 38], "It": [16, 23, 32, 34, 40, 42], "also": [16, 31, 36, 40], "plugin": [16, 31, 42], "resourc": [16, 19, 23, 25, 27, 36], "get_permitted_dag_id": 16, "new_sess": [16, 23], "readabl": [16, 23], "writabl": 16, "By": [16, 31, 34, 40], "default": [16, 23, 32, 33, 34, 36, 37, 38, 41], "individu": [16, 31], "lead": 16, "some": [16, 23], "poor": 16, "recommend": [16, 31, 40], "overrid": [16, 17, 22, 30, 31, 34], "implement": [16, 34], "more": [16, 34, 36, 38], "effici": [16, 23], "contain": [16, 23, 38, 40], "filter": [16, 23], "sqlalchemi": 16, "orm": 16, "security_manag": [16, 17, 30, 31, 34], "secur": [16, 23, 25, 26, 27, 28, 29, 31, 32, 34, 37], "get_url_login": 16, "kwarg": [16, 25, 26, 27, 29], "login": [16, 23, 32, 34, 39], "page": [16, 34, 38, 40], "url": [16, 23], "get_url_logout": 16, "logout": 16, "get_url_user_profil": 16, "info": [16, 23, 34], "get_pars": 16, "gener": [16, 34, 37], "document": [16, 31, 34, 36, 38, 42], "sphinx": [16, 42], "argpars": 16, "api_endpoint": [17, 30], "cli_command": [17, 30], "anonymous_us": [17, 19, 30], "openapi": [17, 30], "constant": [17, 22, 30], "user_edit": [17, 24, 30], "user_stat": [17, 24, 30], "fab_auth_manag": [17, 30], "anonymousus": 18, "flask_login": 18, "anonymoususermixin": 18, "object": [18, 19, 23, 31], "activ": [18, 19, 37], "properti": [18, 19, 23, 27], "perm": [18, 19, 23], "ident": [19, 23], "flask_appbuild": [19, 25, 26, 27, 28, 29, 34], "sqla": 19, "repres": [19, 23], "can_read": [19, 23, 31], "__tablename__": 19, "ab_permiss": 19, "__repr__": 19, "repr": 19, "self": [19, 23, 34, 40], "ab_view_menu": 19, "__eq__": 19, "other": [19, 31, 33], "valu": [19, 23, 31, 32, 36], "__neq__": 19, "assoc_permission_rol": 19, "assign": [19, 31], "ab_rol": [19, 23], "pair": [19, 23, 31], "compris": 19, "combo": 19, "ab_permission_view": 19, "__table_args__": 19, "action_id": 19, "resource_id": 19, "assoc_user_rol": 19, "created_by_fk": 19, "changed_by_fk": 19, "is_authent": 19, "is_act": 19, "is_anonym": 19, "ab_us": [19, 23], "first_nam": [19, 23, 36], "last_nam": [19, 23, 36], "last_login": [19, 23], "login_count": [19, 23], "fail_login_count": [19, 23], "created_on": 19, "changed_on": 19, "created_bi": 19, "changed_bi": 19, "classmethod": 19, "get_user_id": 19, "get_id": 19, "get_nam": 19, "get_full_nam": 19, "registerus": [19, 23], "registr": [19, 23, 34], "ab_register_us": 19, "registration_d": 19, "registration_hash": [19, 23], "add_index_on_ab_user_username_postgr": 19, "tabl": [19, 23, 31, 36], "conn": 19, "kw": 19, "add_index_on_ab_register_user_username_postgr": 19, "existing_rol": 21, "max_num_database_user_sess": 23, "50000": 23, "fabairflowsecuritymanageroverrid": [23, 34], "www": 23, "airflowsecuritymanagerv2": 23, "airflowsecuritymanag": [23, 34], "everyth": 23, "need": [23, 31, 32, 34], "work": [23, 32], "should": [23, 32, 34, 40, 41], "here": [23, 32, 34], "instead": [23, 31, 32, 36, 37], "get_sess": 23, "auth_typ": [23, 34], "type": [23, 34, 38], "is_auth_limit": 23, "bool": 23, "rate": [23, 38], "auth_rate_limit": 23, "auth_role_publ": [23, 34], "public": [23, 34, 36], "oauth_provid": [23, 34], "oauth": 23, "auth_ldap_tls_cacertdir": 23, "ldap": [23, 32, 34], "tl": 23, "ca": 23, "certif": [23, 40], "directori": [23, 40], "auth_ldap_tls_cacertfil": 23, "auth_ldap_tls_certfil": 23, "auth_ldap_tls_keyfil": 23, "kei": [23, 32, 37, 40], "auth_ldap_allow_self_sign": 23, "allow": [23, 31, 32, 34, 36], "sign": [23, 34, 40], "auth_ldap_tls_demand": 23, "demand": 23, "auth_ldap_serv": 23, "server": [23, 40], "auth_ldap_use_tl": 23, "auth_ldap_bind_us": 23, "bind": 23, "auth_ldap_bind_password": 23, "auth_ldap_search": 23, "search": 23, "auth_ldap_search_filt": 23, "auth_ldap_uid_field": 23, "uid": 23, "field": 23, "auth_ldap_firstname_field": 23, "first": [23, 35, 36], "auth_ldap_lastname_field": 23, "last": [23, 31, 36], "auth_ldap_email_field": 23, "auth_ldap_append_domain": 23, "domain": 23, "auth_ldap_username_format": 23, "format": [23, 32, 36, 37], "auth_ldap_group_field": 23, "group": 23, "auth_roles_map": [23, 34], "dict": [23, 34], "map": [23, 34], "auth_user_registration_role_jmespath": 23, "jmespath": 23, "auth_remote_user_env_var": 23, "api_login_allow_multiple_provid": 23, "auth_username_ci": 23, "ci": 23, "auth_ldap_bind_first": 23, "openid_provid": 23, "openid": [23, 34], "auth_type_provider_nam": 23, "auth_user_registr": [23, 34], "Will": 23, "auth_user_registration_rol": [23, 34], "auth_roles_sync_at_login": [23, 34], "auth_role_admin": 23, "admin": [23, 34, 36, 37], "oauth_whitelist": 23, "builtin_rol": 23, "builtin": [23, 25, 26, 27, 28, 29], "auth_view": 23, "obj": 23, "instanc": [23, 31], "registeruser_view": 23, "regist": [23, 34], "user_view": 23, "user_model": 23, "role_model": 23, "action_model": 23, "resource_model": 23, "permission_model": 23, "authdbview": 23, "you": [23, 31, 32, 34, 36, 38, 39, 40, 41], "your": [23, 34], "own": [23, 34], "authldapview": 23, "authoidview": 23, "oid": 23, "authoauthview": 23, "authremoteuserview": 23, "remote_us": [23, 34], "registeruserdbview": 23, "registeruseroidview": 23, "registeruseroauthview": 23, "actionmodelview": [23, 25], "permissionmodelview": [23, 25], "rolemodelview": [23, 26], "registeruser_model": 23, "registerusermodelview": 23, "resourcemodelview": [23, 25], "userdbmodelview": [23, 27], "resetmypasswordview": [23, 28], "resetpasswordview": [23, 28], "userinfoeditview": [23, 28], "userldapmodelview": [23, 27], "useroauthmodelview": [23, 27], "userremoteusermodelview": [23, 27], "useroidmodelview": [23, 27], "userstatschartview": [23, 29], "jwt_manag": 23, "jwt": 23, "extend": 23, "oauth_remot": [23, 34], "remote_app": [23, 34], "provider_nam": 23, "oauth_user_info": 23, "oauth_allow_list": 23, "dag_resourc": 23, "viewer_permiss": [23, 31], "user_permiss": [23, 31], "op_permiss": [23, 31], "admin_permiss": [23, 31], "role_config": 23, "dag_act": 23, "register_view": 23, "relat": [23, 31, 34, 37], "create_login_manag": 23, "create_jwt_manag": 23, "reset_password": 23, "userid": 23, "hash": 23, "save": 23, "int": [23, 34], "clear": [23, 31], "text": 23, "reset_user_sess": 23, "load_user_jwt": 23, "_jwt_header": 23, "jwt_data": 23, "create_builtin_rol": 23, "create_admin_standalon": 23, "random": [23, 36], "so": [23, 34, 36, 38, 41], "create_db": 23, "thei": [23, 31, 36], "don": [23, 31], "get_readable_dag": 23, "get_editable_dag": 23, "get_accessible_dag": 23, "user_act": 23, "get_accessible_dag_id": 23, "get_readable_dag_id": 23, "get_editable_dag_id": 23, "can_access_some_dag": 23, "dag_id": [23, 31], "write": [23, 31, 32], "get_all_permiss": 23, "create_dag_specific_permiss": 23, "can_edit": [23, 31], "can_delet": [23, 31], "along": 23, "access_control": [23, 31], "them": 23, "doe": [23, 36], "iter": 23, "through": [23, 31, 32, 34], "slow": 23, "see": [23, 32, 34, 36, 37, 38, 39, 42], "sync_perm_for_dag": 23, "singl": 23, "prefixed_dag_id": 23, "is_dag_resourc": 23, "determin": 23, "belong": [23, 40], "sure": [23, 32, 34], "our": 23, "bag": 23, "refresh": 23, "button": [23, 34, 35, 37], "dagbag": 23, "call": [23, 31], "function": [23, 32, 37], "whose": 23, "where": [23, 41], "each": [23, 31, 32], "add_permissions_view": 23, "base_action_nam": 23, "expos": 23, "can_add": 23, "etc": 23, "add_permissions_menu": 23, "menu_access": [23, 31], "permission_resourc": 23, "security_cleanup": 23, "baseview": 23, "menu": [23, 31, 37], "cleanup": 23, "unus": 23, "sync_rol": 23, "viewer": [23, 34, 36], "op": [23, 36], "create_perm_vm_for_all_dag": 23, "vm": 23, "insert": 23, "add_homepage_access_to_custom_rol": 23, "websit": [23, 31], "update_admin_permiss": 23, "miss": [23, 31], "except": [23, 34, 37, 41], "becaus": 23, "ones": 23, "clean_perm": 23, "leav": [23, 31], "faulti": 23, "clean": 23, "up": [23, 37], "permission_exists_in_one_or_more_rol": 23, "action_nam": 23, "role_id": 23, "certain": [23, 31], "has_access": 23, "one": [23, 31, 32, 40], "boolean": [23, 38], "perms_include_act": 23, "init_rol": 23, "bulk_sync_rol": 23, "sync_resource_permiss": 23, "popul": 23, "update_rol": 23, "find_rol": 23, "find": 23, "get_all_rol": 23, "get_roles_from_kei": 23, "role_kei": [23, 34], "construct": 23, "thing": 23, "like": [23, 34], "dn": 23, "we": [23, 31, 34, 35, 37, 41], "get_public_rol": 23, "add_us": 23, "hashed_password": 23, "load_us": 23, "user_id": 23, "get_user_by_id": 23, "pk": [23, 27], "count_us": 23, "number": [23, 37], "add_register_us": 23, "rtype": 23, "find_register_us": 23, "update_us": 23, "del_register_us": 23, "register_us": 23, "get_all_us": 23, "update_user_auth_stat": 23, "success": [23, 31], "true": [23, 34, 38], "stat": [23, 31], "done": [23, 34, 41], "upon": [23, 31], "unsuccess": 23, "attempt": 23, "identifi": [23, 34], "possibli": 23, "successfulli": 23, "increment": 23, "get_act": 23, "record": [23, 31], "create_act": 23, "delete_act": 23, "get_resourc": 23, "create_resourc": 23, "get_all_resourc": 23, "delete_resourc": 23, "made": [23, 40], "get_resource_permiss": 23, "retriev": 23, "create_permiss": 23, "delete_permiss": 23, "link": [23, 31, 40], "doesn": 23, "underli": 23, "add_permission_to_rol": 23, "remove_permission_from_rol": 23, "get_oid_identity_url": 23, "oidc": 23, "get_user_rol": 23, "auth_user_ldap": 23, "depend": [23, 27, 31, 37, 41], "python": [23, 32, 34, 39, 40], "auth_user_db": 23, "style": 23, "address": 23, "test": [23, 37, 41], "against": 23, "oauth_user_info_gett": 23, "func": 23, "receiv": [23, 41], "inform": [23, 31, 37, 38, 41], "have": [23, 31, 32, 34, 35, 37, 41], "its": [23, 31], "same": [23, 31], "exampl": [23, 31, 32, 36, 40], "github": 23, "sm": [23, 34], "def": [23, 34], "my_oauth_user_info": 23, "me": [23, 34], "data": [23, 34], "get_oauth_user_info": [23, 34], "resp": [23, 34], "differ": [23, 40], "wai": [23, 34], "oauth_token_gett": 23, "token": 23, "check_author": 23, "specifi": [23, 34], "set_oauth_sess": 23, "oauth_respons": 23, "secret": 23, "get_oauth_token_key_nam": 23, "token_kei": [23, 34], "oauth_token": 23, "get_oauth_token_secret_nam": 23, "token_secret": 23, "oauth_secret": 23, "auth_user_oauth": 23, "userinfo": 23, "column": 23, "auth_user_oid": 23, "auth_user_remote_us": 23, "remot": [23, 32], "get_user_menu_access": 23, "menu_nam": 23, "ldap_extract_list": 23, "ldap_dict": 23, "field_nam": 23, "ldap_extract": 23, "fallback": 23, "filter_roles_by_perm_with_act": 23, "class_permission_nam": [25, 26, 27, 28, 29], "route_bas": [25, 28, 29], "method_permission_nam": [25, 26, 27, 28, 29], "base_permiss": [25, 26, 27, 28, 29], "list_titl": 25, "show_titl": 25, "add_titl": 25, "edit_titl": 25, "label_column": 25, "permissionpairmodelview": 25, "permissionviewmodelview": 25, "list_column": 25, "viewmenumodelview": 25, "customrolemodelview": 26, "multiresourceusermixin": 27, "remap": 27, "usermodelview": 27, "appropri": 27, "class_permission_name_map": 27, "show": [27, 31, 36], "customuserldapmodelview": 27, "customuseroauthmodelview": 27, "customuseroidmodelview": 27, "customuserremoteusermodelview": 27, "customuserdbmodelview": 27, "customuserinfoeditview": 28, "customresetmypasswordview": 28, "customresetpasswordview": 28, "customuserstatschartview": 29, "auth_manag": [30, 31], "__version__": 30, "airflow": [31, 32, 33, 34, 35, 36, 38, 40, 41], "webserv": [31, 32, 33], "ui": [31, 34], "handl": [31, 32, 37], "fab": [31, 34, 35, 40], "pleas": [31, 34, 36, 40], "regard": 31, "ship": 31, "alter": 31, "remain": 31, "unalt": 31, "desir": [31, 34], "necessari": 31, "anonym": [31, 34], "provid": [31, 32, 34, 35, 36, 38, 40, 41], "py": [31, 34, 42], "action_can_read": 31, "resource_dag": 31, "resource_dag_depend": 31, "resource_dag_cod": 31, "resource_dag_run": 31, "resource_dataset": 31, "resource_cluster_act": 31, "resource_pool": 31, "resource_import_error": 31, "resource_dag_warn": 31, "resource_job": 31, "resource_my_password": 31, "action_can_edit": 31, "resource_my_profil": 31, "resource_plugin": 31, "resource_sla_miss": 31, "resource_task_inst": 31, "resource_task_log": 31, "resource_xcom": 31, "resource_websit": 31, "action_can_access_menu": 31, "resource_browse_menu": 31, "resource_doc": 31, "resource_docs_menu": 31, "plu": 31, "addit": [31, 32], "action_can_delet": 31, "action_can_cr": 31, "resource_config": 31, "resource_admin_menu": 31, "resource_connect": 31, "resource_vari": 31, "resource_provid": 31, "possibl": [31, 34, 36], "grant": 31, "revok": [31, 37], "resource_audit_log": 31, "resource_task_reschedul": 31, "resource_trigg": 31, "resource_password": 31, "resource_rol": 31, "treat": 31, "two": 31, "can_dag_read": 31, "can_dag_edit": 31, "deprec": [31, 37], "sinc": [31, 34], "special": 31, "wa": [31, 32, 38], "all_dag": 31, "version": [31, 32, 35, 37, 38, 39, 40, 41], "imag": 31, "creation": 31, "example_python_oper": 31, "via": [31, 37, 39, 40], "role1": 31, "role2": 31, "And": 31, "could": [31, 34], "start": [31, 38], "small": 31, "subset": 31, "those": [31, 40], "match": [31, 40], "standard": [31, 37], "concept": 31, "dagrun": 31, "task": 31, "can_creat": 31, "consist": 31, "ad": [31, 34, 37], "To": [31, 32, 34, 36, 40], "five": 31, "well": [31, 33, 40], "For": [31, 34, 37, 38, 39, 40], "exclus": 31, "who": [31, 34], "either": 31, "being": 31, "act": [31, 34], "try": 31, "example_dag_id": 31, "stabl": [31, 32, 35], "minimum": [31, 39], "config": [31, 32, 34, 37, 38], "post": [31, 37], "connection_id": 31, "patch": 31, "dagsourc": 31, "file_token": 31, "code": [31, 32, 37, 40], "cleartaskinst": 31, "task_id": 31, "dag_run_id": 31, "uri": 31, "event": [31, 37], "eventlog": 31, "audit": 31, "event_log_id": 31, "importerror": 31, "import_error_id": 31, "health": 31, "pool_nam": 31, "taskinst": 31, "task_try_numb": 31, "variable_kei": 31, "xcomentri": 31, "xcom": 31, "xcom_kei": 31, "homepag": 31, "brows": 31, "render": 31, "metadata": [31, 32], "redirect": [31, 37], "extern": 31, "trigger": 31, "mark": [31, 37], "block": 31, "fail": 31, "tree": 31, "graph": 31, "durat": 31, "tri": [31, 32], "land": 31, "time": 31, "toggl": 31, "paus": 31, "statu": 31, "gantt": 31, "chart": 31, "up_for_retri": 31, "autocomplet": [31, 37], "doc": [31, 37, 42], "job": 31, "my": [31, 35, 37], "profil": 31, "sla": 31, "reschedul": 31, "These": 31, "directli": 31, "encod": [31, 32], "themselv": 31, "place": 31, "conflict": 31, "inevit": 31, "resolut": 31, "strategi": 31, "As": 31, "result": 31, "consid": 31, "argument": 31, "suppli": [31, 34], "complet": 31, "authorit": 31, "present": 31, "few": [31, 34], "effect": 31, "overwrit": 31, "previous": [31, 34, 36, 38], "than": 31, "example_fine_grained_access": 31, "start_dat": 31, "pendulum": 31, "datetim": 31, "2021": [31, 40], "tz": 31, "utc": 31, "wipe": 31, "example_no_fine_grained_access": 31, "convers": 31, "altogeth": 31, "won": 31, "make": [31, 32, 34, 36, 37], "dangl": 31, "example_indifferent_to_fine_grained_access": 31, "In": [31, 32, 34], "case": [31, 41], "defer": 31, "mai": [31, 32], "been": 31, "previou": [31, 40], "question": 31, "system": 31, "wide": 31, "take": 31, "over": 31, "separ": [32, 41], "web": [32, 34], "auth_backend": 32, "11": [32, 37, 40], "without": [32, 36], "pose": 32, "risk": 32, "publicli": 32, "3": [32, 39], "support": [32, 34, 37, 39], "turn": 32, "below": [32, 33, 36, 38, 39, 40], "wish": [32, 34], "awar": 32, "enabl": [32, 37, 38], "layer": 32, "front": 32, "follow": [32, 33, 34, 40, 41], "cfg": [32, 38], "rest": 32, "modul": 32, "how": [32, 34, 40], "keytab": 32, "servic": 32, "fulli": 32, "qualifi": 32, "domainnam": 32, "realm": 32, "princip": 32, "full": 32, "order": [32, 34], "user_nam": 32, "within": 32, "base64": 32, "send": 32, "http": [32, 34, 40], "sampl": 32, "curl": [32, 40], "valid": [32, 40, 42], "setup": 32, "endpoint_url": 32, "localhost": 32, "8080": 32, "x": 32, "v1": 32, "still": 32, "credenti": 32, "though": 32, "might": [32, 34, 41], "anoth": [32, 34], "under": [32, 37], "abl": 32, "pass": [32, 34, 36], "must": [32, 34], "app": [32, 34, 37, 39], "invok": 32, "applic": 32, "fn": 32, "callabl": [32, 34], "arbitrari": 32, "execut": 32, "befor": [32, 34], "after": 32, "client": 32, "mode": 32, "create_client_sess": 32, "attribut": 32, "authbas": 32, "section": [32, 34], "come": 33, "store": 33, "erd": 33, "topic": 33, "understand": [33, 34], "aspect": 33, "control": 33, "prior": 34, "account": 34, "peter": 34, "parker": 34, "spiderman": 34, "superhero": 34, "org": [34, 36, 40], "deactiv": 34, "entri": 34, "airflow_hom": 34, "webserver_config": 34, "Be": 34, "checkout": 34, "parser": 34, "interpol": 34, "escap": 34, "otherwis": 34, "leak": 34, "One": 34, "simplest": 34, "mechan": 34, "interfac": [34, 37], "do": [34, 36, 40], "builder": [34, 37, 39], "rbac": 34, "automat": [34, 42], "due": 34, "authlib": 34, "select": [34, 40], "oauth2": 34, "githubloc": 34, "twitter": 34, "linkedin": 34, "googl": [34, 39], "azur": [34, 35, 37], "openshift": 34, "okta": 34, "keycloak": 34, "keycloak_before_17": 34, "describ": [34, 38, 40], "auth_db": 34, "wsgi": 34, "middlewar": 34, "veri": 34, "form": [34, 37], "spnego": 34, "leverag": 34, "current_app": 34, "const": 34, "auth_remote_us": 34, "class": [34, 37, 39], "custommiddlewar": 34, "__init__": 34, "wsgi_app": 34, "__call__": 34, "start_respons": 34, "logic": 34, "recaptcha_private_kei": 34, "private_kei": 34, "recaptcha_public_kei": 34, "public_kei": 34, "mail_serv": 34, "smtp": 34, "gmail": [34, 40], "com": [34, 40], "mail_use_tl": 34, "mail_usernam": 34, "yourappemail": 34, "mail_password": 34, "passwordformail": 34, "mail_default_send": 34, "sender": 34, "packag": [34, 38], "mail": 34, "pip": [34, 39, 40], "framework": 34, "third": 34, "parti": [34, 41], "refer": 34, "chosen": 34, "comment": [34, 37], "step": [34, 40], "what": 34, "auth_oauth": 34, "o": [34, 36, 40], "everi": 34, "icon": 34, "fa": 34, "access_token": 34, "client_id": 34, "getenv": 34, "oauth_app_id": 34, "client_secret": 34, "oauth_app_secret": 34, "api_base_url": 34, "client_kwarg": 34, "scope": [34, 41], "access_token_url": 34, "authorize_url": 34, "request_token_url": 34, "customsecuritymanag": 34, "replac": 34, "security_manager_class": 34, "path": [34, 37], "union": 34, "getlogg": 34, "__name__": 34, "setlevel": 34, "airflow__logging__fab_logging_level": 34, "fab_admin_rol": 34, "fab_viewer_rol": 34, "fab_public_rol": 34, "team_id_a_from_github": 34, "123": 34, "real": 34, "team_id_b_from_github": 34, "456": 34, "team_pars": 34, "team_payload": 34, "pars": 34, "payload": 34, "map_rol": 34, "team_list": 34, "expect": 34, "output": [34, 36], "team_role_map": 34, "githubteamauthor": 34, "ever": 34, "dpgaspar": 34, "blob": 34, "master": 34, "l550": 34, "behalf": 34, "now": 34, "queri": 34, "membership": 34, "user_data": 34, "team_data": 34, "debug": 34, "f": [34, 36, 37], "nteam": 34, "github_": 34, "apach": [35, 38, 40], "38957": [35, 37], "renam": [35, 37], "allowed_filter_attr": [35, 37], "allowed_sort_attr": [35, 37], "38626": [35, 37], "38872": [35, 37], "releas": [35, 37, 39], "beta": 35, "9": [36, 37, 39], "were": [36, 38], "core": [36, 37, 38], "usag": [36, 37], "h": 36, "group_or_command": 36, "choic": 36, "r": 36, "u": 36, "v": 36, "verbos": 36, "l": [36, 40], "p": 36, "prompt": 36, "string": [36, 37], "equal": 36, "filepath": 36, "foo": 36, "bar": 36, "jon": 36, "jondo": 36, "yaml": 36, "plain": 36, "pretti": 36, "sort": 36, "indent": 36, "space": 36, "commit": 37, "high": 37, "level": 37, "changelog": 37, "latest": [37, 41], "2024": 37, "04": 37, "15": 37, "subject": 37, "f8104325b7": 37, "ruf019": 37, "unnecessari": 37, "38950": 37, "c3bb80da93": 37, "12": [37, 40], "5fa80b6aea": 37, "prepar": [37, 41], "1st": 37, "wave": 37, "rc1": 37, "april": 37, "38863": 37, "53cd7173b4": 37, "fix": [37, 41], "6d3d2075ae": 37, "07": 37, "try002": 37, "38801": 37, "e700f4150a": 37, "03": 37, "30": 37, "25": 37, "256911aa62": 37, "38451": 37, "7776e9154d": 37, "20": 37, "upgrad": [37, 41], "38319": 37, "0a74928894": 37, "18": 37, "bump": 37, "ruff": 37, "38240": 37, "2e35854a05": 37, "abstract": 37, "37915": 37, "c0b849ad2b": 37, "avoid": 37, "assert": 37, "outsid": 37, "37718": 37, "c6f34394c4": 37, "improv": 37, "suffix": 37, "38029": 37, "3f52790d42": 37, "06": 37, "resolv": 37, "g004": 37, "statement": 37, "37873": 37, "fd4dfd875d": 37, "useless": 37, "37889": 37, "3211a5fcea": 37, "next": [37, 41], "37904": 37, "89e7f3e7bd": 37, "05": 37, "37881": 37, "30f7b2abe6": 37, "too": 37, "broad": 37, "noqa": 37, "37862": 37, "9b17ff3aa3": 37, "02": 37, "26": 37, "37570": 37, "16d2671704": 37, "queuedev": 37, "datasetdagrunqueu": 37, "37176": 37, "79603f9302": 37, "19": 37, "swagger": 37, "intern": 37, "37525": 37, "f2ea8a3e17": 37, "audit_log": 37, "37501": 37, "68e20aa702": 37, "17": 37, "flag": 37, "37507": 37, "5a0be392e6": 37, "16": 37, "37488": 37, "4551c592b2": 37, "14": 37, "until": 37, "keep": 37, "37421": 37, "54a400fcb6": 37, "readi": 37, "37362": 37, "ec97a07197": 37, "13": 37, "get_app": 37, "37397": 37, "28f94f8891": 37, "move": 37, "import_error": 37, "37292": 37, "00ed46769": 37, "09": 37, "d401": 37, "37283": 37, "e99cfbbd51": 37, "37233": 37, "daa2bceba1": 37, "next_url": 37, "37225": 37, "dec2662190": 37, "01": 37, "feat": 37, "switch": 37, "36876": 37, "0fce3b6047": 37, "28": 37, "37044": 37, "ce246c0ed8": 37, "count": 37, "36589": 37, "18d2498e44": 37, "36672": 37, "c439ab87c4": 37, "build": [37, 40, 42], "process": [37, 42], "hatchl": 37, "36537": 37, "28cad70223": 37, "36232": 37, "2093b6f3b9": 37, "inherit": 37, "36538": 37, "dec78ab3f1": 37, "mssql": 37, "36514": 37, "e28627f6a5": 37, "36347": 37, "6937ae7647": 37, "2023": 37, "speed": 37, "breez": 37, "simplifi": 37, "36499": 37, "83bdc297ce": 37, "36445": 37, "341d5b747d": 37, "23": 37, "fetur": 37, "36391": 37, "b15d5578da": 37, "re": 37, "appli": 37, "2nd": 37, "decemb": 37, "36380": 37, "2be7149598": 37, "21": 37, "36343": 37, "e9ba37bb58": 37, "snippet": 37, "docstr": 37, "36262": 37, "f7f7183617": 37, "36120": 37, "4d96a9a3a1": 37, "connexion": 37, "36209": 37, "357355ac09": 37, "is_authorized_cluster_act": 37, "36175": 37, "1eca667e5f": 37, "35926": 37, "embed": 38, "7": 38, "look": 38, "airflow__fab__auth_rate_limit": 38, "top": [39, 40], "6": 39, "re2": 39, "download": 40, "offici": 40, "most": 40, "choos": 40, "drop": 40, "down": 40, "left": 40, "sdist": 40, "whl": 40, "origin": 40, "checksum": 40, "signatur": 40, "softwar": 40, "foundat": 40, "asc": 40, "sha512": 40, "abov": 40, "pgp": 40, "essenti": 40, "sha": 40, "gpg": 40, "relev": 40, "distribut": 40, "main": [40, 41], "mirror": 40, "pgpk": 40, "ka": 40, "binari": 40, "guid": 40, "pgpv": 40, "tar": 40, "gz": 40, "sat": 40, "sep": 40, "49": 40, "54": 40, "bst": 40, "rsa": 40, "cde15c6e4d3a8ec4ecf4ba4b6674e08ad7de406f": 40, "issuer": 40, "kaxilnaik": 40, "good": [40, 41], "kaxil": 40, "naik": 40, "aka": 40, "warn": 40, "certifi": 40, "trust": 40, "indic": 40, "owner": 40, "primari": 40, "fingerprint": 40, "cde1": 40, "5c6e": 40, "4d3a": 40, "8ec4": 40, "ecf4": 40, "ba4b": 40, "6674": 40, "e08a": 40, "d7de": 40, "406f": 40, "correct": 40, "worri": 40, "why": 40, "know": 40, "sum": 40, "shasum": 40, "512": 40, "diff": 40, "local": 40, "script": 40, "bin": 40, "bash": 40, "package_vers": 40, "package_nam": 40, "provider_download_dir": 40, "mktemp": 40, "d": 40, "dep": 40, "dest": 40, "apache_airflow_providers_fab": 40, "py3": 40, "echo": 40, "la": 40, "onc": 40, "instruct": [40, 41], "chapter": 40, "temporari": 40, "folder": 40, "independ": 41, "vulner": 41, "publish": 41, "found": 41, "pypi": 41, "develop": 41, "alwai": 41, "branch": 41, "strict": 41, "semver": 41, "polici": 41, "major": 41, "break": 41, "minor": 41, "patchlevel": 41, "bug": 41, "bugfix": 41, "rule": 41, "critic": 41, "reason": 41, "out": 41, "band": 41, "stakehold": 41, "decid": 41, "cherri": 41, "pick": 41, "older": 41, "mix": 41, "govern": 41, "interest": 41, "stub": 42, "convert": 42, "dure": 42, "conf": 42}, "objects": {"airflow.providers": [[30, 0, 0, "-", "fab"]], "airflow.providers.fab": [[30, 1, 1, "", "__version__"], [17, 0, 0, "-", "auth_manager"]], "airflow.providers.fab.auth_manager": [[4, 0, 0, "-", "api"], [5, 0, 0, "-", "api_endpoints"], [9, 0, 0, "-", "cli_commands"], [15, 0, 0, "-", "decorators"], [16, 0, 0, "-", "fab_auth_manager"], [19, 0, 0, "-", "models"], [20, 0, 0, "-", "openapi"], [22, 0, 0, "-", "security_manager"], [24, 0, 0, "-", "views"]], "airflow.providers.fab.auth_manager.api": [[3, 0, 0, "-", "auth"]], "airflow.providers.fab.auth_manager.api.auth": [[1, 0, 0, "-", "backend"]], "airflow.providers.fab.auth_manager.api.auth.backend": [[0, 0, 0, "-", "basic_auth"], [2, 0, 0, "-", "kerberos_auth"]], "airflow.providers.fab.auth_manager.api.auth.backend.basic_auth": [[0, 1, 1, "", "CLIENT_AUTH"], [0, 1, 1, "", "T"], [0, 2, 1, "", "auth_current_user"], [0, 2, 1, "", "init_app"], [0, 2, 1, "", "requires_authentication"]], "airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth": [[2, 1, 1, "", "CLIENT_AUTH"], [2, 2, 1, "", "find_user"], [2, 1, 1, "", "init_app"], [2, 1, 1, "", "log"], [2, 1, 1, "", "requires_authentication"]], "airflow.providers.fab.auth_manager.api_endpoints": [[6, 0, 0, "-", "role_and_permission_endpoint"], [7, 0, 0, "-", "user_endpoint"]], "airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint": [[6, 2, 1, "", "delete_role"], [6, 2, 1, "", "get_permissions"], [6, 2, 1, "", "get_role"], [6, 2, 1, "", "get_roles"], [6, 2, 1, "", "patch_role"], [6, 2, 1, "", "post_role"]], "airflow.providers.fab.auth_manager.api_endpoints.user_endpoint": [[7, 2, 1, "", "delete_user"], [7, 2, 1, "", "get_user"], [7, 2, 1, "", "get_users"], [7, 2, 1, "", "patch_user"], [7, 2, 1, "", "post_user"]], "airflow.providers.fab.auth_manager.cli_commands": [[8, 0, 0, "-", "definition"], [10, 0, 0, "-", "role_command"], [11, 0, 0, "-", "sync_perm_command"], [12, 0, 0, "-", "user_command"], [13, 0, 0, "-", "utils"]], "airflow.providers.fab.auth_manager.cli_commands.definition": [[8, 1, 1, "", "ARG_CREATE_ROLE"], [8, 1, 1, "", "ARG_EMAIL"], [8, 1, 1, "", "ARG_EMAIL_OPTIONAL"], [8, 1, 1, "", "ARG_FIRSTNAME"], [8, 1, 1, "", "ARG_INCLUDE_DAGS"], [8, 1, 1, "", "ARG_LASTNAME"], [8, 1, 1, "", "ARG_LIST_ROLES"], [8, 1, 1, "", "ARG_PASSWORD"], [8, 1, 1, "", "ARG_PERMISSIONS"], [8, 1, 1, "", "ARG_ROLE"], [8, 1, 1, "", "ARG_ROLES"], [8, 1, 1, "", "ARG_ROLE_ACTION"], [8, 1, 1, "", "ARG_ROLE_ACTION_REQUIRED"], [8, 1, 1, "", "ARG_ROLE_EXPORT"], [8, 1, 1, "", "ARG_ROLE_EXPORT_FMT"], [8, 1, 1, "", "ARG_ROLE_IMPORT"], [8, 1, 1, "", "ARG_ROLE_RESOURCE"], [8, 1, 1, "", "ARG_USERNAME"], [8, 1, 1, "", "ARG_USERNAME_OPTIONAL"], [8, 1, 1, "", "ARG_USER_EXPORT"], [8, 1, 1, "", "ARG_USER_IMPORT"], [8, 1, 1, "", "ARG_USE_RANDOM_PASSWORD"], [8, 1, 1, "", "ROLES_COMMANDS"], [8, 1, 1, "", "SYNC_PERM_COMMAND"], [8, 1, 1, "", "USERS_COMMANDS"]], "airflow.providers.fab.auth_manager.cli_commands.role_command": [[10, 2, 1, "", "roles_add_perms"], [10, 2, 1, "", "roles_create"], [10, 2, 1, "", "roles_del_perms"], [10, 2, 1, "", "roles_delete"], [10, 2, 1, "", "roles_export"], [10, 2, 1, "", "roles_import"], [10, 2, 1, "", "roles_list"]], "airflow.providers.fab.auth_manager.cli_commands.sync_perm_command": [[11, 2, 1, "", "sync_perm"]], "airflow.providers.fab.auth_manager.cli_commands.user_command": [[12, 3, 1, "", "UserSchema"], [12, 1, 1, "", "add_role"], [12, 1, 1, "", "remove_role"], [12, 2, 1, "", "user_reset_password"], [12, 2, 1, "", "users_create"], [12, 2, 1, "", "users_delete"], [12, 2, 1, "", "users_export"], [12, 2, 1, "", "users_import"], [12, 2, 1, "", "users_list"], [12, 2, 1, "", "users_manage_role"]], "airflow.providers.fab.auth_manager.cli_commands.user_command.UserSchema": [[12, 4, 1, "", "email"], [12, 4, 1, "", "firstname"], [12, 4, 1, "", "id"], [12, 4, 1, "", "lastname"], [12, 4, 1, "", "roles"], [12, 4, 1, "", "username"]], "airflow.providers.fab.auth_manager.cli_commands.utils": [[13, 2, 1, "", "get_application_builder"]], "airflow.providers.fab.auth_manager.decorators": [[14, 0, 0, "-", "auth"]], "airflow.providers.fab.auth_manager.decorators.auth": [[14, 1, 1, "", "T"], [14, 1, 1, "", "log"]], "airflow.providers.fab.auth_manager.fab_auth_manager": [[16, 3, 1, "", "FabAuthManager"], [16, 2, 1, "", "get_parser"]], "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager": [[16, 5, 1, "", "get_api_endpoints"], [16, 5, 1, "", "get_cli_commands"], [16, 5, 1, "", "get_permitted_dag_ids"], [16, 5, 1, "", "get_url_login"], [16, 5, 1, "", "get_url_logout"], [16, 5, 1, "", "get_url_user_profile"], [16, 5, 1, "", "get_user"], [16, 5, 1, "", "get_user_display_name"], [16, 5, 1, "", "init"], [16, 5, 1, "", "is_authorized_configuration"], [16, 5, 1, "", "is_authorized_connection"], [16, 5, 1, "", "is_authorized_custom_view"], [16, 5, 1, "", "is_authorized_dag"], [16, 5, 1, "", "is_authorized_dataset"], [16, 5, 1, "", "is_authorized_pool"], [16, 5, 1, "", "is_authorized_variable"], [16, 5, 1, "", "is_authorized_view"], [16, 5, 1, "", "is_logged_in"], [16, 5, 1, "", "security_manager"]], "airflow.providers.fab.auth_manager.models": [[19, 3, 1, "", "Action"], [19, 1, 1, "", "Identity"], [19, 3, 1, "", "Permission"], [19, 3, 1, "", "RegisterUser"], [19, 3, 1, "", "Resource"], [19, 3, 1, "", "Role"], [19, 3, 1, "", "User"], [19, 2, 1, "", "add_index_on_ab_register_user_username_postgres"], [19, 2, 1, "", "add_index_on_ab_user_username_postgres"], [18, 0, 0, "-", "anonymous_user"], [19, 1, 1, "", "assoc_permission_role"], [19, 1, 1, "", "assoc_user_role"]], "airflow.providers.fab.auth_manager.models.Action": [[19, 5, 1, "", "__repr__"], [19, 4, 1, "", "__tablename__"], [19, 4, 1, "", "id"], [19, 4, 1, "", "name"]], "airflow.providers.fab.auth_manager.models.Permission": [[19, 5, 1, "", "__repr__"], [19, 4, 1, "", "__table_args__"], [19, 4, 1, "", "__tablename__"], [19, 4, 1, "", "action"], [19, 4, 1, "", "action_id"], [19, 4, 1, "", "id"], [19, 4, 1, "", "resource"], [19, 4, 1, "", "resource_id"]], "airflow.providers.fab.auth_manager.models.RegisterUser": [[19, 4, 1, "", "__tablename__"], [19, 4, 1, "", "email"], [19, 4, 1, "", "first_name"], [19, 4, 1, "", "id"], [19, 4, 1, "", "last_name"], [19, 4, 1, "", "password"], [19, 4, 1, "", "registration_date"], [19, 4, 1, "", "registration_hash"], [19, 4, 1, "", "username"]], "airflow.providers.fab.auth_manager.models.Resource": [[19, 5, 1, "", "__eq__"], [19, 5, 1, "", "__neq__"], [19, 5, 1, "", "__repr__"], [19, 4, 1, "", "__tablename__"], [19, 4, 1, "", "id"], [19, 4, 1, "", "name"]], "airflow.providers.fab.auth_manager.models.Role": [[19, 5, 1, "", "__repr__"], [19, 4, 1, "", "__tablename__"], [19, 4, 1, "", "id"], [19, 4, 1, "", "name"], [19, 4, 1, "", "permissions"]], "airflow.providers.fab.auth_manager.models.User": [[19, 5, 1, "", "__repr__"], [19, 4, 1, "", "__tablename__"], [19, 4, 1, "", "active"], [19, 4, 1, "", "changed_by"], [19, 6, 1, "", "changed_by_fk"], [19, 4, 1, "", "changed_on"], [19, 4, 1, "", "created_by"], [19, 6, 1, "", "created_by_fk"], [19, 4, 1, "", "created_on"], [19, 4, 1, "", "email"], [19, 4, 1, "", "fail_login_count"], [19, 4, 1, "", "first_name"], [19, 5, 1, "", "get_full_name"], [19, 5, 1, "", "get_id"], [19, 5, 1, "", "get_name"], [19, 5, 1, "", "get_user_id"], [19, 4, 1, "", "id"], [19, 6, 1, "", "is_active"], [19, 6, 1, "", "is_anonymous"], [19, 6, 1, "", "is_authenticated"], [19, 4, 1, "", "last_login"], [19, 4, 1, "", "last_name"], [19, 4, 1, "", "login_count"], [19, 4, 1, "", "password"], [19, 6, 1, "", "perms"], [19, 4, 1, "", "roles"], [19, 4, 1, "", "username"]], "airflow.providers.fab.auth_manager.models.anonymous_user": [[18, 3, 1, "", "AnonymousUser"]], "airflow.providers.fab.auth_manager.models.anonymous_user.AnonymousUser": [[18, 6, 1, "", "perms"], [18, 6, 1, "", "roles"]], "airflow.providers.fab.auth_manager.security_manager": [[21, 0, 0, "-", "constants"], [23, 0, 0, "-", "override"]], "airflow.providers.fab.auth_manager.security_manager.constants": [[21, 1, 1, "", "EXISTING_ROLES"]], "airflow.providers.fab.auth_manager.security_manager.override": [[23, 3, 1, "", "FabAirflowSecurityManagerOverride"], [23, 1, 1, "", "MAX_NUM_DATABASE_USER_SESSIONS"], [23, 1, 1, "", "log"]], "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride": [[23, 4, 1, "", "ADMIN_PERMISSIONS"], [23, 4, 1, "", "DAG_ACTIONS"], [23, 4, 1, "", "DAG_RESOURCES"], [23, 4, 1, "", "OP_PERMISSIONS"], [23, 4, 1, "", "ROLE_CONFIGS"], [23, 4, 1, "", "USER_PERMISSIONS"], [23, 4, 1, "", "VIEWER_PERMISSIONS"], [23, 4, 1, "", "action_model"], [23, 4, 1, "", "actionmodelview"], [23, 5, 1, "", "add_homepage_access_to_custom_roles"], [23, 5, 1, "", "add_permission_to_role"], [23, 5, 1, "", "add_permissions_menu"], [23, 5, 1, "", "add_permissions_view"], [23, 5, 1, "", "add_register_user"], [23, 5, 1, "", "add_role"], [23, 5, 1, "", "add_user"], [23, 6, 1, "", "api_login_allow_multiple_providers"], [23, 6, 1, "", "auth_ldap_allow_self_signed"], [23, 6, 1, "", "auth_ldap_append_domain"], [23, 6, 1, "", "auth_ldap_bind_first"], [23, 6, 1, "", "auth_ldap_bind_password"], [23, 6, 1, "", "auth_ldap_bind_user"], [23, 6, 1, "", "auth_ldap_email_field"], [23, 6, 1, "", "auth_ldap_firstname_field"], [23, 6, 1, "", "auth_ldap_group_field"], [23, 6, 1, "", "auth_ldap_lastname_field"], [23, 6, 1, "", "auth_ldap_search"], [23, 6, 1, "", "auth_ldap_search_filter"], [23, 6, 1, "", "auth_ldap_server"], [23, 6, 1, "", "auth_ldap_tls_cacertdir"], [23, 6, 1, "", "auth_ldap_tls_cacertfile"], [23, 6, 1, "", "auth_ldap_tls_certfile"], [23, 6, 1, "", "auth_ldap_tls_demand"], [23, 6, 1, "", "auth_ldap_tls_keyfile"], [23, 6, 1, "", "auth_ldap_uid_field"], [23, 6, 1, "", "auth_ldap_use_tls"], [23, 6, 1, "", "auth_ldap_username_format"], [23, 6, 1, "", "auth_rate_limit"], [23, 6, 1, "", "auth_remote_user_env_var"], [23, 6, 1, "", "auth_role_admin"], [23, 6, 1, "", "auth_role_public"], [23, 6, 1, "", "auth_roles_mapping"], [23, 6, 1, "", "auth_roles_sync_at_login"], [23, 6, 1, "", "auth_type"], [23, 6, 1, "", "auth_type_provider_name"], [23, 5, 1, "", "auth_user_db"], [23, 5, 1, "", "auth_user_ldap"], [23, 5, 1, "", "auth_user_oauth"], [23, 5, 1, "", "auth_user_oid"], [23, 6, 1, "", "auth_user_registration"], [23, 6, 1, "", "auth_user_registration_role"], [23, 6, 1, "", "auth_user_registration_role_jmespath"], [23, 5, 1, "", "auth_user_remote_user"], [23, 6, 1, "", "auth_username_ci"], [23, 4, 1, "", "auth_view"], [23, 4, 1, "", "authdbview"], [23, 4, 1, "", "authldapview"], [23, 4, 1, "", "authoauthview"], [23, 4, 1, "", "authoidview"], [23, 4, 1, "", "authremoteuserview"], [23, 6, 1, "", "builtin_roles"], [23, 5, 1, "", "bulk_sync_roles"], [23, 5, 1, "", "can_access_some_dags"], [23, 5, 1, "", "check_authorization"], [23, 5, 1, "", "clean_perms"], [23, 5, 1, "", "count_users"], [23, 5, 1, "", "create_action"], [23, 5, 1, "", "create_admin_standalone"], [23, 5, 1, "", "create_builtin_roles"], [23, 5, 1, "", "create_dag_specific_permissions"], [23, 5, 1, "", "create_db"], [23, 5, 1, "", "create_jwt_manager"], [23, 5, 1, "", "create_login_manager"], [23, 5, 1, "", "create_perm_vm_for_all_dag"], [23, 5, 1, "", "create_permission"], [23, 5, 1, "", "create_resource"], [23, 5, 1, "", "del_register_user"], [23, 5, 1, "", "delete_action"], [23, 5, 1, "", "delete_permission"], [23, 5, 1, "", "delete_resource"], [23, 5, 1, "", "delete_role"], [23, 5, 1, "", "filter_roles_by_perm_with_action"], [23, 5, 1, "", "find_register_user"], [23, 5, 1, "", "find_role"], [23, 5, 1, "", "find_user"], [23, 5, 1, "", "get_accessible_dag_ids"], [23, 5, 1, "", "get_accessible_dags"], [23, 5, 1, "", "get_action"], [23, 5, 1, "", "get_all_permissions"], [23, 5, 1, "", "get_all_resources"], [23, 5, 1, "", "get_all_roles"], [23, 5, 1, "", "get_all_users"], [23, 5, 1, "", "get_editable_dag_ids"], [23, 5, 1, "", "get_editable_dags"], [23, 5, 1, "", "get_oauth_token_key_name"], [23, 5, 1, "", "get_oauth_token_secret_name"], [23, 5, 1, "", "get_oauth_user_info"], [23, 5, 1, "", "get_oid_identity_url"], [23, 5, 1, "", "get_permission"], [23, 5, 1, "", "get_public_role"], [23, 5, 1, "", "get_readable_dag_ids"], [23, 5, 1, "", "get_readable_dags"], [23, 5, 1, "", "get_resource"], [23, 5, 1, "", "get_resource_permissions"], [23, 5, 1, "", "get_roles_from_keys"], [23, 6, 1, "", "get_session"], [23, 5, 1, "", "get_user_by_id"], [23, 5, 1, "", "get_user_menu_access"], [23, 5, 1, "", "get_user_roles"], [23, 5, 1, "", "init_role"], [23, 6, 1, "", "is_auth_limited"], [23, 5, 1, "", "is_dag_resource"], [23, 4, 1, "", "jwt_manager"], [23, 5, 1, "", "ldap_extract"], [23, 5, 1, "", "ldap_extract_list"], [23, 5, 1, "", "load_user"], [23, 5, 1, "", "load_user_jwt"], [23, 4, 1, "", "oauth"], [23, 4, 1, "", "oauth_allow_list"], [23, 6, 1, "", "oauth_providers"], [23, 4, 1, "", "oauth_remotes"], [23, 5, 1, "", "oauth_token_getter"], [23, 4, 1, "", "oauth_user_info"], [23, 5, 1, "", "oauth_user_info_getter"], [23, 6, 1, "", "oauth_whitelists"], [23, 4, 1, "", "oid"], [23, 6, 1, "", "openid_providers"], [23, 5, 1, "", "permission_exists_in_one_or_more_roles"], [23, 4, 1, "", "permission_model"], [23, 4, 1, "", "permissionmodelview"], [23, 5, 1, "", "perms_include_action"], [23, 5, 1, "", "prefixed_dag_id"], [23, 5, 1, "", "register_views"], [23, 4, 1, "", "registeruser_model"], [23, 4, 1, "", "registeruser_view"], [23, 4, 1, "", "registeruserdbview"], [23, 4, 1, "", "registerusermodelview"], [23, 4, 1, "", "registeruseroauthview"], [23, 4, 1, "", "registeruseroidview"], [23, 5, 1, "", "remove_permission_from_role"], [23, 5, 1, "", "reset_password"], [23, 5, 1, "", "reset_user_sessions"], [23, 4, 1, "", "resetmypasswordview"], [23, 4, 1, "", "resetpasswordview"], [23, 4, 1, "", "resource_model"], [23, 4, 1, "", "resourcemodelview"], [23, 4, 1, "", "role_model"], [23, 4, 1, "", "rolemodelview"], [23, 5, 1, "", "security_cleanup"], [23, 5, 1, "", "set_oauth_session"], [23, 5, 1, "", "sync_perm_for_dag"], [23, 5, 1, "", "sync_resource_permissions"], [23, 5, 1, "", "sync_roles"], [23, 5, 1, "", "update_admin_permission"], [23, 5, 1, "", "update_role"], [23, 5, 1, "", "update_user"], [23, 5, 1, "", "update_user_auth_stat"], [23, 4, 1, "", "user_model"], [23, 4, 1, "", "user_view"], [23, 4, 1, "", "userdbmodelview"], [23, 4, 1, "", "userinfoeditview"], [23, 4, 1, "", "userldapmodelview"], [23, 4, 1, "", "useroauthmodelview"], [23, 4, 1, "", "useroidmodelview"], [23, 4, 1, "", "userremoteusermodelview"], [23, 4, 1, "", "userstatschartview"]], "airflow.providers.fab.auth_manager.views": [[25, 0, 0, "-", "permissions"], [26, 0, 0, "-", "roles_list"], [27, 0, 0, "-", "user"], [28, 0, 0, "-", "user_edit"], [29, 0, 0, "-", "user_stats"]], "airflow.providers.fab.auth_manager.views.permissions": [[25, 3, 1, "", "ActionModelView"], [25, 3, 1, "", "PermissionPairModelView"], [25, 3, 1, "", "ResourceModelView"]], "airflow.providers.fab.auth_manager.views.permissions.ActionModelView": [[25, 4, 1, "", "add_title"], [25, 4, 1, "", "base_permissions"], [25, 4, 1, "", "class_permission_name"], [25, 4, 1, "", "edit_title"], [25, 4, 1, "", "label_columns"], [25, 4, 1, "", "list_title"], [25, 4, 1, "", "method_permission_name"], [25, 4, 1, "", "route_base"], [25, 4, 1, "", "show_title"]], "airflow.providers.fab.auth_manager.views.permissions.PermissionPairModelView": [[25, 4, 1, "", "add_title"], [25, 4, 1, "", "base_permissions"], [25, 4, 1, "", "class_permission_name"], [25, 4, 1, "", "edit_title"], [25, 4, 1, "", "label_columns"], [25, 4, 1, "", "list_columns"], [25, 4, 1, "", "list_title"], [25, 4, 1, "", "method_permission_name"], [25, 4, 1, "", "route_base"], [25, 4, 1, "", "show_title"]], "airflow.providers.fab.auth_manager.views.permissions.ResourceModelView": [[25, 4, 1, "", "add_title"], [25, 4, 1, "", "base_permissions"], [25, 4, 1, "", "class_permission_name"], [25, 4, 1, "", "edit_title"], [25, 4, 1, "", "label_columns"], [25, 4, 1, "", "list_title"], [25, 4, 1, "", "method_permission_name"], [25, 4, 1, "", "route_base"], [25, 4, 1, "", "show_title"]], "airflow.providers.fab.auth_manager.views.roles_list": [[26, 3, 1, "", "CustomRoleModelView"]], "airflow.providers.fab.auth_manager.views.roles_list.CustomRoleModelView": [[26, 4, 1, "", "base_permissions"], [26, 4, 1, "", "class_permission_name"], [26, 4, 1, "", "method_permission_name"]], "airflow.providers.fab.auth_manager.views.user": [[27, 3, 1, "", "CustomUserDBModelView"], [27, 3, 1, "", "CustomUserLDAPModelView"], [27, 3, 1, "", "CustomUserOAuthModelView"], [27, 3, 1, "", "CustomUserOIDModelView"], [27, 3, 1, "", "CustomUserRemoteUserModelView"], [27, 3, 1, "", "MultiResourceUserMixin"]], "airflow.providers.fab.auth_manager.views.user.CustomUserDBModelView": [[27, 4, 1, "", "base_permissions"], [27, 4, 1, "", "class_permission_name_mapping"], [27, 4, 1, "", "method_permission_name"]], "airflow.providers.fab.auth_manager.views.user.CustomUserLDAPModelView": [[27, 4, 1, "", "base_permissions"], [27, 4, 1, "", "class_permission_name_mapping"], [27, 4, 1, "", "method_permission_name"]], "airflow.providers.fab.auth_manager.views.user.CustomUserRemoteUserModelView": [[27, 4, 1, "", "base_permissions"], [27, 4, 1, "", "class_permission_name_mapping"], [27, 4, 1, "", "method_permission_name"]], "airflow.providers.fab.auth_manager.views.user.MultiResourceUserMixin": [[27, 4, 1, "", "base_permissions"], [27, 6, 1, "", "class_permission_name"], [27, 4, 1, "", "class_permission_name_mapping"], [27, 4, 1, "", "method_permission_name"], [27, 5, 1, "", "show"]], "airflow.providers.fab.auth_manager.views.user_edit": [[28, 3, 1, "", "CustomResetMyPasswordView"], [28, 3, 1, "", "CustomResetPasswordView"], [28, 3, 1, "", "CustomUserInfoEditView"]], "airflow.providers.fab.auth_manager.views.user_edit.CustomResetMyPasswordView": [[28, 4, 1, "", "base_permissions"], [28, 4, 1, "", "class_permission_name"], [28, 4, 1, "", "method_permission_name"]], "airflow.providers.fab.auth_manager.views.user_edit.CustomResetPasswordView": [[28, 4, 1, "", "base_permissions"], [28, 4, 1, "", "class_permission_name"], [28, 4, 1, "", "method_permission_name"]], "airflow.providers.fab.auth_manager.views.user_edit.CustomUserInfoEditView": [[28, 4, 1, "", "base_permissions"], [28, 4, 1, "", "class_permission_name"], [28, 4, 1, "", "method_permission_name"], [28, 4, 1, "", "route_base"]], "airflow.providers.fab.auth_manager.views.user_stats": [[29, 3, 1, "", "CustomUserStatsChartView"]], "airflow.providers.fab.auth_manager.views.user_stats.CustomUserStatsChartView": [[29, 4, 1, "", "base_permissions"], [29, 4, 1, "", "class_permission_name"], [29, 4, 1, "", "method_permission_name"], [29, 4, 1, "", "route_base"]]}, "objtypes": {"0": "py:module", "1": "py:data", "2": "py:function", "3": "py:class", "4": "py:attribute", "5": "py:method", "6": "py:property"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "data", "Python data"], "2": ["py", "function", "Python function"], "3": ["py", "class", "Python class"], "4": ["py", "attribute", "Python attribute"], "5": ["py", "method", "Python method"], "6": ["py", "property", "Python property"]}, "titleterms": {"airflow": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 37, 39], "provid": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 37, 39], "fab": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 36, 37, 38, 39], "auth_manag": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "api": [0, 1, 2, 3, 4, 32, 42], "auth": [0, 1, 2, 3, 14, 33], "backend": [0, 1, 2], "basic_auth": 0, "modul": [0, 2, 6, 7, 8, 10, 11, 12, 13, 14, 16, 18, 21, 23, 25, 26, 27, 28, 29], "content": [0, 2, 6, 7, 8, 10, 11, 12, 13, 14, 16, 18, 19, 21, 23, 25, 26, 27, 28, 29, 30], "function": [0, 2, 6, 7, 10, 11, 12, 13, 16, 19], "attribut": [0, 2, 12, 19, 23], "submodul": [1, 5, 9, 15, 17, 19, 22, 24], "kerberos_auth": 2, "subpackag": [3, 4, 17, 30], "api_endpoint": [5, 6, 7], "role_and_permission_endpoint": 6, "user_endpoint": 7, "cli_command": [8, 9, 10, 11, 12, 13], "definit": 8, "role_command": 10, "sync_perm_command": 11, "user_command": 12, "class": [12, 16, 18, 19, 23, 25, 26, 27, 28, 29], "util": 13, "decor": [14, 15], "fab_auth_manag": 16, "model": [18, 19], "anonymous_us": 18, "packag": [19, 30, 37, 39, 40], "openapi": 20, "security_manag": [21, 22, 23], "constant": 21, "overrid": 23, "view": [24, 25, 26, 27, 28, 29], "permiss": [25, 31], "roles_list": 26, "user": [27, 31, 36], "user_edit": 28, "user_stat": 29, "access": 31, "control": 31, "default": 31, "role": [31, 36], "public": 31, "viewer": 31, "op": 31, "admin": 31, "custom": 31, "dag": 31, "level": 31, "resourc": 31, "base": [31, 34], "order": 31, "preced": 31, "authent": [32, 34], "disabl": 32, "kerbero": 32, "basic": 32, "roll": 32, "your": 32, "own": 32, "flask": 33, "appbuild": 33, "manag": 33, "webserv": 34, "password": [34, 36], "other": 34, "method": 34, "exampl": 34, "us": 34, "team": 34, "author": 34, "github": 34, "oauth": 34, "changelog": 35, "1": [35, 37], "0": [35, 37], "4": [35, 37], "bug": 35, "fix": 35, "3": [35, 37], "2": [35, 37], "yank": 35, "cli": 36, "command": 36, "posit": 36, "argument": 36, "sub": 36, "add": 36, "name": 36, "creat": 36, "delet": 36, "export": 36, "import": 36, "list": 36, "remov": 36, "reset": 36, "perm": 36, "del": 36, "sync": 36, "apach": [37, 39], "configur": 38, "refer": [38, 42], "section": 38, "auth_rate_limit": 38, "instal": [39, 40], "requir": 39, "from": 40, "sourc": 40, "releas": [40, 41], "integr": 40, "verifi": 40, "pypi": 40, "secur": 41, "patch": 41, "rest": 42}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.viewcode": 1, "sphinx.ext.intersphinx": 1, "sphinx": 57}, "alltitles": {"airflow.providers.fab.auth_manager.api.auth.backend.basic_auth": [[0, "module-airflow.providers.fab.auth_manager.api.auth.backend.basic_auth"]], "Module Contents": [[0, "module-contents"], [2, "module-contents"], [6, "module-contents"], [7, "module-contents"], [8, "module-contents"], [10, "module-contents"], [11, "module-contents"], [12, "module-contents"], [13, "module-contents"], [14, "module-contents"], [16, "module-contents"], [18, "module-contents"], [21, "module-contents"], [23, "module-contents"], [25, "module-contents"], [26, "module-contents"], [27, "module-contents"], [28, "module-contents"], [29, "module-contents"]], "Functions": [[0, "functions"], [2, "functions"], [6, "functions"], [7, "functions"], [10, "functions"], [11, "functions"], [12, "functions"], [13, "functions"], [16, "functions"], [19, "functions"]], "Attributes": [[0, "attributes"], [2, "attributes"], [12, "attributes"], [19, "attributes"], [23, "attributes"]], "airflow.providers.fab.auth_manager.api.auth.backend": [[1, "module-airflow.providers.fab.auth_manager.api.auth.backend"]], "Submodules": [[1, "submodules"], [5, "submodules"], [9, "submodules"], [15, "submodules"], [17, "submodules"], [19, "submodules"], [22, "submodules"], [24, "submodules"]], "airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth": [[2, "module-airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth"]], "airflow.providers.fab.auth_manager.api.auth": [[3, "module-airflow.providers.fab.auth_manager.api.auth"]], "Subpackages": [[3, "subpackages"], [4, "subpackages"], [17, "subpackages"], [30, "subpackages"]], "airflow.providers.fab.auth_manager.api": [[4, "module-airflow.providers.fab.auth_manager.api"]], "airflow.providers.fab.auth_manager.api_endpoints": [[5, "module-airflow.providers.fab.auth_manager.api_endpoints"]], "airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint": [[6, "module-airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint"]], "airflow.providers.fab.auth_manager.api_endpoints.user_endpoint": [[7, "module-airflow.providers.fab.auth_manager.api_endpoints.user_endpoint"]], "airflow.providers.fab.auth_manager.cli_commands.definition": [[8, "module-airflow.providers.fab.auth_manager.cli_commands.definition"]], "airflow.providers.fab.auth_manager.cli_commands": [[9, "module-airflow.providers.fab.auth_manager.cli_commands"]], "airflow.providers.fab.auth_manager.cli_commands.role_command": [[10, "module-airflow.providers.fab.auth_manager.cli_commands.role_command"]], "airflow.providers.fab.auth_manager.cli_commands.sync_perm_command": [[11, "module-airflow.providers.fab.auth_manager.cli_commands.sync_perm_command"]], "airflow.providers.fab.auth_manager.cli_commands.user_command": [[12, "module-airflow.providers.fab.auth_manager.cli_commands.user_command"]], "Classes": [[12, "classes"], [16, "classes"], [18, "classes"], [19, "classes"], [23, "classes"], [25, "classes"], [26, "classes"], [27, "classes"], [28, "classes"], [29, "classes"]], "airflow.providers.fab.auth_manager.cli_commands.utils": [[13, "module-airflow.providers.fab.auth_manager.cli_commands.utils"]], "airflow.providers.fab.auth_manager.decorators.auth": [[14, "module-airflow.providers.fab.auth_manager.decorators.auth"]], "airflow.providers.fab.auth_manager.decorators": [[15, "module-airflow.providers.fab.auth_manager.decorators"]], "airflow.providers.fab.auth_manager.fab_auth_manager": [[16, "module-airflow.providers.fab.auth_manager.fab_auth_manager"]], "airflow.providers.fab.auth_manager": [[17, "module-airflow.providers.fab.auth_manager"]], "airflow.providers.fab.auth_manager.models.anonymous_user": [[18, "module-airflow.providers.fab.auth_manager.models.anonymous_user"]], "airflow.providers.fab.auth_manager.models": [[19, "module-airflow.providers.fab.auth_manager.models"]], "Package Contents": [[19, "package-contents"], [30, "package-contents"]], "airflow.providers.fab.auth_manager.openapi": [[20, "module-airflow.providers.fab.auth_manager.openapi"]], "airflow.providers.fab.auth_manager.security_manager.constants": [[21, "module-airflow.providers.fab.auth_manager.security_manager.constants"]], "airflow.providers.fab.auth_manager.security_manager": [[22, "module-airflow.providers.fab.auth_manager.security_manager"]], "airflow.providers.fab.auth_manager.security_manager.override": [[23, "module-airflow.providers.fab.auth_manager.security_manager.override"]], "airflow.providers.fab.auth_manager.views": [[24, "module-airflow.providers.fab.auth_manager.views"]], "airflow.providers.fab.auth_manager.views.permissions": [[25, "module-airflow.providers.fab.auth_manager.views.permissions"]], "airflow.providers.fab.auth_manager.views.roles_list": [[26, "module-airflow.providers.fab.auth_manager.views.roles_list"]], "airflow.providers.fab.auth_manager.views.user": [[27, "module-airflow.providers.fab.auth_manager.views.user"]], "airflow.providers.fab.auth_manager.views.user_edit": [[28, "module-airflow.providers.fab.auth_manager.views.user_edit"]], "airflow.providers.fab.auth_manager.views.user_stats": [[29, "module-airflow.providers.fab.auth_manager.views.user_stats"]], "airflow.providers.fab": [[30, "module-airflow.providers.fab"]], "Access Control": [[31, "access-control"]], "Default Roles": [[31, "default-roles"]], "Public": [[31, "public"]], "Viewer": [[31, "viewer"]], "User": [[31, "user"]], "Op": [[31, "op"]], "Admin": [[31, "admin"]], "Custom Roles": [[31, "custom-roles"]], "DAG Level Role": [[31, "dag-level-role"]], "Permissions": [[31, "permissions"]], "Resource-Based permissions": [[31, "resource-based-permissions"]], "DAG-level permissions": [[31, "dag-level-permissions"]], "Order of precedence for DAG-level permissions": [[31, "order-of-precedence-for-dag-level-permissions"]], "API Authentication": [[32, "api-authentication"]], "Disable authentication": [[32, "disable-authentication"]], "Kerberos authentication": [[32, "kerberos-authentication"]], "Basic authentication": [[32, "basic-authentication"]], "Roll your own API authentication": [[32, "roll-your-own-api-authentication"]], "Flask AppBuilder (FAB) auth manager": [[33, "flask-appbuilder-fab-auth-manager"]], "Webserver authentication": [[34, "webserver-authentication"]], "Password": [[34, "password"]], "Other Methods": [[34, "other-methods"]], "Example using team based Authorization with GitHub OAuth": [[34, "example-using-team-based-authorization-with-github-oauth"]], "Changelog": [[35, "changelog"]], "1.0.4": [[35, "id1"], [37, "id1"]], "Bug Fixes": [[35, "bug-fixes"], [35, "id3"]], "1.0.3": [[35, "id2"], [37, "id2"]], "1.0.2": [[35, "id4"], [37, "id3"]], "1.0.0 (YANKED)": [[35, "yanked"]], "FAB CLI Commands": [[36, "fab-cli-commands"]], "Positional Arguments": [[36, "positional-arguments"], [36, "positional-arguments_repeat1"], [36, "positional-arguments_repeat2"], [36, "positional-arguments_repeat3"], [36, "positional-arguments_repeat4"], [36, "positional-arguments_repeat5"], [36, "positional-arguments_repeat6"], [36, "positional-arguments_repeat7"], [36, "positional-arguments_repeat8"], [36, "positional-arguments_repeat9"], [36, "positional-arguments_repeat10"]], "Sub-commands": [[36, "Sub-commands"], [36, "Sub-commands_repeat1"], [36, "Sub-commands_repeat2"]], "users": [[36, "users"]], "add-role": [[36, "add-role"]], "Named Arguments": [[36, "named-arguments"], [36, "named-arguments_repeat1"], [36, "named-arguments_repeat2"], [36, "named-arguments_repeat3"], [36, "named-arguments_repeat4"], [36, "named-arguments_repeat5"], [36, "named-arguments_repeat6"], [36, "named-arguments_repeat7"], [36, "named-arguments_repeat8"], [36, "named-arguments_repeat9"], [36, "named-arguments_repeat10"], [36, "named-arguments_repeat11"], [36, "named-arguments_repeat12"], [36, "named-arguments_repeat13"], [36, "named-arguments_repeat14"], [36, "named-arguments_repeat15"]], "create": [[36, "create"], [36, "create_repeat1"]], "delete": [[36, "delete"], [36, "delete_repeat1"]], "export": [[36, "export"], [36, "export_repeat1"]], "import": [[36, "import"], [36, "import_repeat1"]], "list": [[36, "list"], [36, "list_repeat1"]], "remove-role": [[36, "remove-role"]], "reset-password": [[36, "reset-password"]], "roles": [[36, "roles"]], "add-perms": [[36, "add-perms"]], "del-perms": [[36, "del-perms"]], "sync-perm": [[36, "sync-perm"]], "Package apache-airflow-providers-fab": [[37, "package-apache-airflow-providers-fab"]], "1.0.1": [[37, "id4"]], "1.0.0": [[37, "id5"]], "Configuration Reference": [[38, "configuration-reference"]], "Sections:": [[38, "sections"]], "[fab]": [[38, "fab"]], "auth_rate_limited": [[38, "auth-rate-limited"]], "apache-airflow-providers-fab": [[39, "apache-airflow-providers-fab"]], "apache-airflow-providers-fab package": [[39, "apache-airflow-providers-fab-package"]], "Provider package": [[39, "provider-package"]], "Installation": [[39, "installation"]], "Requirements": [[39, "requirements"]], "Installing from sources": [[40, "installing-from-sources"]], "Released packages": [[40, "released-packages"]], "Release integrity": [[40, "release-integrity"]], "Verifying PyPI releases": [[40, "verifying-pypi-releases"]], "Releasing security patches": [[41, "releasing-security-patches"]], "REST API Reference": [[42, "rest-api-reference"]]}, "indexentries": {"client_auth (in module airflow.providers.fab.auth_manager.api.auth.backend.basic_auth)": [[0, "airflow.providers.fab.auth_manager.api.auth.backend.basic_auth.CLIENT_AUTH"]], "t (in module airflow.providers.fab.auth_manager.api.auth.backend.basic_auth)": [[0, "airflow.providers.fab.auth_manager.api.auth.backend.basic_auth.T"]], "airflow.providers.fab.auth_manager.api.auth.backend.basic_auth": [[0, "module-airflow.providers.fab.auth_manager.api.auth.backend.basic_auth"]], "auth_current_user() (in module airflow.providers.fab.auth_manager.api.auth.backend.basic_auth)": [[0, "airflow.providers.fab.auth_manager.api.auth.backend.basic_auth.auth_current_user"]], "init_app() (in module airflow.providers.fab.auth_manager.api.auth.backend.basic_auth)": [[0, "airflow.providers.fab.auth_manager.api.auth.backend.basic_auth.init_app"]], "module": [[0, "module-airflow.providers.fab.auth_manager.api.auth.backend.basic_auth"], [1, "module-airflow.providers.fab.auth_manager.api.auth.backend"], [2, "module-airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth"], [3, "module-airflow.providers.fab.auth_manager.api.auth"], [4, "module-airflow.providers.fab.auth_manager.api"], [5, "module-airflow.providers.fab.auth_manager.api_endpoints"], [6, "module-airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint"], [7, "module-airflow.providers.fab.auth_manager.api_endpoints.user_endpoint"], [8, "module-airflow.providers.fab.auth_manager.cli_commands.definition"], [9, "module-airflow.providers.fab.auth_manager.cli_commands"], [10, "module-airflow.providers.fab.auth_manager.cli_commands.role_command"], [11, "module-airflow.providers.fab.auth_manager.cli_commands.sync_perm_command"], [12, "module-airflow.providers.fab.auth_manager.cli_commands.user_command"], [13, "module-airflow.providers.fab.auth_manager.cli_commands.utils"], [14, "module-airflow.providers.fab.auth_manager.decorators.auth"], [15, "module-airflow.providers.fab.auth_manager.decorators"], [16, "module-airflow.providers.fab.auth_manager.fab_auth_manager"], [17, "module-airflow.providers.fab.auth_manager"], [18, "module-airflow.providers.fab.auth_manager.models.anonymous_user"], [19, "module-airflow.providers.fab.auth_manager.models"], [20, "module-airflow.providers.fab.auth_manager.openapi"], [21, "module-airflow.providers.fab.auth_manager.security_manager.constants"], [22, "module-airflow.providers.fab.auth_manager.security_manager"], [23, "module-airflow.providers.fab.auth_manager.security_manager.override"], [24, "module-airflow.providers.fab.auth_manager.views"], [25, "module-airflow.providers.fab.auth_manager.views.permissions"], [26, "module-airflow.providers.fab.auth_manager.views.roles_list"], [27, "module-airflow.providers.fab.auth_manager.views.user"], [28, "module-airflow.providers.fab.auth_manager.views.user_edit"], [29, "module-airflow.providers.fab.auth_manager.views.user_stats"], [30, "module-airflow.providers.fab"]], "requires_authentication() (in module airflow.providers.fab.auth_manager.api.auth.backend.basic_auth)": [[0, "airflow.providers.fab.auth_manager.api.auth.backend.basic_auth.requires_authentication"]], "airflow.providers.fab.auth_manager.api.auth.backend": [[1, "module-airflow.providers.fab.auth_manager.api.auth.backend"]], "client_auth (in module airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth)": [[2, "airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth.CLIENT_AUTH"]], "airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth": [[2, "module-airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth"]], "find_user() (in module airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth)": [[2, "airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth.find_user"]], "init_app (in module airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth)": [[2, "airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth.init_app"]], "log (in module airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth)": [[2, "airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth.log"]], "requires_authentication (in module airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth)": [[2, "airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth.requires_authentication"]], "airflow.providers.fab.auth_manager.api.auth": [[3, "module-airflow.providers.fab.auth_manager.api.auth"]], "airflow.providers.fab.auth_manager.api": [[4, "module-airflow.providers.fab.auth_manager.api"]], "airflow.providers.fab.auth_manager.api_endpoints": [[5, "module-airflow.providers.fab.auth_manager.api_endpoints"]], "airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint": [[6, "module-airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint"]], "delete_role() (in module airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint)": [[6, "airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint.delete_role"]], "get_permissions() (in module airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint)": [[6, "airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint.get_permissions"]], "get_role() (in module airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint)": [[6, "airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint.get_role"]], "get_roles() (in module airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint)": [[6, "airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint.get_roles"]], "patch_role() (in module airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint)": [[6, "airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint.patch_role"]], "post_role() (in module airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint)": [[6, "airflow.providers.fab.auth_manager.api_endpoints.role_and_permission_endpoint.post_role"]], "airflow.providers.fab.auth_manager.api_endpoints.user_endpoint": [[7, "module-airflow.providers.fab.auth_manager.api_endpoints.user_endpoint"]], "delete_user() (in module airflow.providers.fab.auth_manager.api_endpoints.user_endpoint)": [[7, "airflow.providers.fab.auth_manager.api_endpoints.user_endpoint.delete_user"]], "get_user() (in module airflow.providers.fab.auth_manager.api_endpoints.user_endpoint)": [[7, "airflow.providers.fab.auth_manager.api_endpoints.user_endpoint.get_user"]], "get_users() (in module airflow.providers.fab.auth_manager.api_endpoints.user_endpoint)": [[7, "airflow.providers.fab.auth_manager.api_endpoints.user_endpoint.get_users"]], "patch_user() (in module airflow.providers.fab.auth_manager.api_endpoints.user_endpoint)": [[7, "airflow.providers.fab.auth_manager.api_endpoints.user_endpoint.patch_user"]], "post_user() (in module airflow.providers.fab.auth_manager.api_endpoints.user_endpoint)": [[7, "airflow.providers.fab.auth_manager.api_endpoints.user_endpoint.post_user"]], "arg_create_role (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_CREATE_ROLE"]], "arg_email (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_EMAIL"]], "arg_email_optional (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_EMAIL_OPTIONAL"]], "arg_firstname (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_FIRSTNAME"]], "arg_include_dags (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_INCLUDE_DAGS"]], "arg_lastname (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_LASTNAME"]], "arg_list_roles (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_LIST_ROLES"]], "arg_password (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_PASSWORD"]], "arg_permissions (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_PERMISSIONS"]], "arg_role (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_ROLE"]], "arg_roles (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_ROLES"]], "arg_role_action (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_ROLE_ACTION"]], "arg_role_action_required (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_ROLE_ACTION_REQUIRED"]], "arg_role_export (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_ROLE_EXPORT"]], "arg_role_export_fmt (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_ROLE_EXPORT_FMT"]], "arg_role_import (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_ROLE_IMPORT"]], "arg_role_resource (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_ROLE_RESOURCE"]], "arg_username (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_USERNAME"]], "arg_username_optional (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_USERNAME_OPTIONAL"]], "arg_user_export (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_USER_EXPORT"]], "arg_user_import (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_USER_IMPORT"]], "arg_use_random_password (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ARG_USE_RANDOM_PASSWORD"]], "roles_commands (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.ROLES_COMMANDS"]], "sync_perm_command (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.SYNC_PERM_COMMAND"]], "users_commands (in module airflow.providers.fab.auth_manager.cli_commands.definition)": [[8, "airflow.providers.fab.auth_manager.cli_commands.definition.USERS_COMMANDS"]], "airflow.providers.fab.auth_manager.cli_commands.definition": [[8, "module-airflow.providers.fab.auth_manager.cli_commands.definition"]], "airflow.providers.fab.auth_manager.cli_commands": [[9, "module-airflow.providers.fab.auth_manager.cli_commands"]], "airflow.providers.fab.auth_manager.cli_commands.role_command": [[10, "module-airflow.providers.fab.auth_manager.cli_commands.role_command"]], "roles_add_perms() (in module airflow.providers.fab.auth_manager.cli_commands.role_command)": [[10, "airflow.providers.fab.auth_manager.cli_commands.role_command.roles_add_perms"]], "roles_create() (in module airflow.providers.fab.auth_manager.cli_commands.role_command)": [[10, "airflow.providers.fab.auth_manager.cli_commands.role_command.roles_create"]], "roles_del_perms() (in module airflow.providers.fab.auth_manager.cli_commands.role_command)": [[10, "airflow.providers.fab.auth_manager.cli_commands.role_command.roles_del_perms"]], "roles_delete() (in module airflow.providers.fab.auth_manager.cli_commands.role_command)": [[10, "airflow.providers.fab.auth_manager.cli_commands.role_command.roles_delete"]], "roles_export() (in module airflow.providers.fab.auth_manager.cli_commands.role_command)": [[10, "airflow.providers.fab.auth_manager.cli_commands.role_command.roles_export"]], "roles_import() (in module airflow.providers.fab.auth_manager.cli_commands.role_command)": [[10, "airflow.providers.fab.auth_manager.cli_commands.role_command.roles_import"]], "roles_list() (in module airflow.providers.fab.auth_manager.cli_commands.role_command)": [[10, "airflow.providers.fab.auth_manager.cli_commands.role_command.roles_list"]], "airflow.providers.fab.auth_manager.cli_commands.sync_perm_command": [[11, "module-airflow.providers.fab.auth_manager.cli_commands.sync_perm_command"]], "sync_perm() (in module airflow.providers.fab.auth_manager.cli_commands.sync_perm_command)": [[11, "airflow.providers.fab.auth_manager.cli_commands.sync_perm_command.sync_perm"]], "userschema (class in airflow.providers.fab.auth_manager.cli_commands.user_command)": [[12, "airflow.providers.fab.auth_manager.cli_commands.user_command.UserSchema"]], "add_role (in module airflow.providers.fab.auth_manager.cli_commands.user_command)": [[12, "airflow.providers.fab.auth_manager.cli_commands.user_command.add_role"]], "airflow.providers.fab.auth_manager.cli_commands.user_command": [[12, "module-airflow.providers.fab.auth_manager.cli_commands.user_command"]], "email (airflow.providers.fab.auth_manager.cli_commands.user_command.userschema attribute)": [[12, "airflow.providers.fab.auth_manager.cli_commands.user_command.UserSchema.email"]], "firstname (airflow.providers.fab.auth_manager.cli_commands.user_command.userschema attribute)": [[12, "airflow.providers.fab.auth_manager.cli_commands.user_command.UserSchema.firstname"]], "id (airflow.providers.fab.auth_manager.cli_commands.user_command.userschema attribute)": [[12, "airflow.providers.fab.auth_manager.cli_commands.user_command.UserSchema.id"]], "lastname (airflow.providers.fab.auth_manager.cli_commands.user_command.userschema attribute)": [[12, "airflow.providers.fab.auth_manager.cli_commands.user_command.UserSchema.lastname"]], "remove_role (in module airflow.providers.fab.auth_manager.cli_commands.user_command)": [[12, "airflow.providers.fab.auth_manager.cli_commands.user_command.remove_role"]], "roles (airflow.providers.fab.auth_manager.cli_commands.user_command.userschema attribute)": [[12, "airflow.providers.fab.auth_manager.cli_commands.user_command.UserSchema.roles"]], "user_reset_password() (in module airflow.providers.fab.auth_manager.cli_commands.user_command)": [[12, "airflow.providers.fab.auth_manager.cli_commands.user_command.user_reset_password"]], "username (airflow.providers.fab.auth_manager.cli_commands.user_command.userschema attribute)": [[12, "airflow.providers.fab.auth_manager.cli_commands.user_command.UserSchema.username"]], "users_create() (in module airflow.providers.fab.auth_manager.cli_commands.user_command)": [[12, "airflow.providers.fab.auth_manager.cli_commands.user_command.users_create"]], "users_delete() (in module airflow.providers.fab.auth_manager.cli_commands.user_command)": [[12, "airflow.providers.fab.auth_manager.cli_commands.user_command.users_delete"]], "users_export() (in module airflow.providers.fab.auth_manager.cli_commands.user_command)": [[12, "airflow.providers.fab.auth_manager.cli_commands.user_command.users_export"]], "users_import() (in module airflow.providers.fab.auth_manager.cli_commands.user_command)": [[12, "airflow.providers.fab.auth_manager.cli_commands.user_command.users_import"]], "users_list() (in module airflow.providers.fab.auth_manager.cli_commands.user_command)": [[12, "airflow.providers.fab.auth_manager.cli_commands.user_command.users_list"]], "users_manage_role() (in module airflow.providers.fab.auth_manager.cli_commands.user_command)": [[12, "airflow.providers.fab.auth_manager.cli_commands.user_command.users_manage_role"]], "airflow.providers.fab.auth_manager.cli_commands.utils": [[13, "module-airflow.providers.fab.auth_manager.cli_commands.utils"]], "get_application_builder() (in module airflow.providers.fab.auth_manager.cli_commands.utils)": [[13, "airflow.providers.fab.auth_manager.cli_commands.utils.get_application_builder"]], "t (in module airflow.providers.fab.auth_manager.decorators.auth)": [[14, "airflow.providers.fab.auth_manager.decorators.auth.T"]], "airflow.providers.fab.auth_manager.decorators.auth": [[14, "module-airflow.providers.fab.auth_manager.decorators.auth"]], "log (in module airflow.providers.fab.auth_manager.decorators.auth)": [[14, "airflow.providers.fab.auth_manager.decorators.auth.log"]], "airflow.providers.fab.auth_manager.decorators": [[15, "module-airflow.providers.fab.auth_manager.decorators"]], "fabauthmanager (class in airflow.providers.fab.auth_manager.fab_auth_manager)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager"]], "airflow.providers.fab.auth_manager.fab_auth_manager": [[16, "module-airflow.providers.fab.auth_manager.fab_auth_manager"]], "get_api_endpoints() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.get_api_endpoints"]], "get_cli_commands() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager static method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.get_cli_commands"]], "get_parser() (in module airflow.providers.fab.auth_manager.fab_auth_manager)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.get_parser"]], "get_permitted_dag_ids() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.get_permitted_dag_ids"]], "get_url_login() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.get_url_login"]], "get_url_logout() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.get_url_logout"]], "get_url_user_profile() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.get_url_user_profile"]], "get_user() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.get_user"]], "get_user_display_name() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.get_user_display_name"]], "init() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.init"]], "is_authorized_configuration() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.is_authorized_configuration"]], "is_authorized_connection() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.is_authorized_connection"]], "is_authorized_custom_view() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.is_authorized_custom_view"]], "is_authorized_dag() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.is_authorized_dag"]], "is_authorized_dataset() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.is_authorized_dataset"]], "is_authorized_pool() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.is_authorized_pool"]], "is_authorized_variable() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.is_authorized_variable"]], "is_authorized_view() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.is_authorized_view"]], "is_logged_in() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.is_logged_in"]], "security_manager() (airflow.providers.fab.auth_manager.fab_auth_manager.fabauthmanager method)": [[16, "airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager.security_manager"]], "airflow.providers.fab.auth_manager": [[17, "module-airflow.providers.fab.auth_manager"]], "anonymoususer (class in airflow.providers.fab.auth_manager.models.anonymous_user)": [[18, "airflow.providers.fab.auth_manager.models.anonymous_user.AnonymousUser"]], "airflow.providers.fab.auth_manager.models.anonymous_user": [[18, "module-airflow.providers.fab.auth_manager.models.anonymous_user"]], "perms (airflow.providers.fab.auth_manager.models.anonymous_user.anonymoususer property)": [[18, "airflow.providers.fab.auth_manager.models.anonymous_user.AnonymousUser.perms"]], "roles (airflow.providers.fab.auth_manager.models.anonymous_user.anonymoususer property)": [[18, "airflow.providers.fab.auth_manager.models.anonymous_user.AnonymousUser.roles"]], "action (class in airflow.providers.fab.auth_manager.models)": [[19, "airflow.providers.fab.auth_manager.models.Action"]], "identity (in module airflow.providers.fab.auth_manager.models)": [[19, "airflow.providers.fab.auth_manager.models.Identity"]], "permission (class in airflow.providers.fab.auth_manager.models)": [[19, "airflow.providers.fab.auth_manager.models.Permission"]], "registeruser (class in airflow.providers.fab.auth_manager.models)": [[19, "airflow.providers.fab.auth_manager.models.RegisterUser"]], "resource (class in airflow.providers.fab.auth_manager.models)": [[19, "airflow.providers.fab.auth_manager.models.Resource"]], "role (class in airflow.providers.fab.auth_manager.models)": [[19, "airflow.providers.fab.auth_manager.models.Role"]], "user (class in airflow.providers.fab.auth_manager.models)": [[19, "airflow.providers.fab.auth_manager.models.User"]], "__eq__() (airflow.providers.fab.auth_manager.models.resource method)": [[19, "airflow.providers.fab.auth_manager.models.Resource.__eq__"]], "__neq__() (airflow.providers.fab.auth_manager.models.resource method)": [[19, "airflow.providers.fab.auth_manager.models.Resource.__neq__"]], "__repr__() (airflow.providers.fab.auth_manager.models.action method)": [[19, "airflow.providers.fab.auth_manager.models.Action.__repr__"]], "__repr__() (airflow.providers.fab.auth_manager.models.permission method)": [[19, "airflow.providers.fab.auth_manager.models.Permission.__repr__"]], "__repr__() (airflow.providers.fab.auth_manager.models.resource method)": [[19, "airflow.providers.fab.auth_manager.models.Resource.__repr__"]], "__repr__() (airflow.providers.fab.auth_manager.models.role method)": [[19, "airflow.providers.fab.auth_manager.models.Role.__repr__"]], "__repr__() (airflow.providers.fab.auth_manager.models.user method)": [[19, "airflow.providers.fab.auth_manager.models.User.__repr__"]], "__table_args__ (airflow.providers.fab.auth_manager.models.permission attribute)": [[19, "airflow.providers.fab.auth_manager.models.Permission.__table_args__"]], "__tablename__ (airflow.providers.fab.auth_manager.models.action attribute)": [[19, "airflow.providers.fab.auth_manager.models.Action.__tablename__"]], "__tablename__ (airflow.providers.fab.auth_manager.models.permission attribute)": [[19, "airflow.providers.fab.auth_manager.models.Permission.__tablename__"]], "__tablename__ (airflow.providers.fab.auth_manager.models.registeruser attribute)": [[19, "airflow.providers.fab.auth_manager.models.RegisterUser.__tablename__"]], "__tablename__ (airflow.providers.fab.auth_manager.models.resource attribute)": [[19, "airflow.providers.fab.auth_manager.models.Resource.__tablename__"]], "__tablename__ (airflow.providers.fab.auth_manager.models.role attribute)": [[19, "airflow.providers.fab.auth_manager.models.Role.__tablename__"]], "__tablename__ (airflow.providers.fab.auth_manager.models.user attribute)": [[19, "airflow.providers.fab.auth_manager.models.User.__tablename__"]], "action (airflow.providers.fab.auth_manager.models.permission attribute)": [[19, "airflow.providers.fab.auth_manager.models.Permission.action"]], "action_id (airflow.providers.fab.auth_manager.models.permission attribute)": [[19, "airflow.providers.fab.auth_manager.models.Permission.action_id"]], "active (airflow.providers.fab.auth_manager.models.user attribute)": [[19, "airflow.providers.fab.auth_manager.models.User.active"]], "add_index_on_ab_register_user_username_postgres() (in module airflow.providers.fab.auth_manager.models)": [[19, "airflow.providers.fab.auth_manager.models.add_index_on_ab_register_user_username_postgres"]], "add_index_on_ab_user_username_postgres() (in module airflow.providers.fab.auth_manager.models)": [[19, "airflow.providers.fab.auth_manager.models.add_index_on_ab_user_username_postgres"]], "airflow.providers.fab.auth_manager.models": [[19, "module-airflow.providers.fab.auth_manager.models"]], "assoc_permission_role (in module airflow.providers.fab.auth_manager.models)": [[19, "airflow.providers.fab.auth_manager.models.assoc_permission_role"]], "assoc_user_role (in module airflow.providers.fab.auth_manager.models)": [[19, "airflow.providers.fab.auth_manager.models.assoc_user_role"]], "changed_by (airflow.providers.fab.auth_manager.models.user attribute)": [[19, "airflow.providers.fab.auth_manager.models.User.changed_by"]], "changed_by_fk (airflow.providers.fab.auth_manager.models.user property)": [[19, "airflow.providers.fab.auth_manager.models.User.changed_by_fk"]], "changed_on (airflow.providers.fab.auth_manager.models.user attribute)": [[19, "airflow.providers.fab.auth_manager.models.User.changed_on"]], "created_by (airflow.providers.fab.auth_manager.models.user attribute)": [[19, "airflow.providers.fab.auth_manager.models.User.created_by"]], "created_by_fk (airflow.providers.fab.auth_manager.models.user property)": [[19, "airflow.providers.fab.auth_manager.models.User.created_by_fk"]], "created_on (airflow.providers.fab.auth_manager.models.user attribute)": [[19, "airflow.providers.fab.auth_manager.models.User.created_on"]], "email (airflow.providers.fab.auth_manager.models.registeruser attribute)": [[19, "airflow.providers.fab.auth_manager.models.RegisterUser.email"]], "email (airflow.providers.fab.auth_manager.models.user attribute)": [[19, "airflow.providers.fab.auth_manager.models.User.email"]], "fail_login_count (airflow.providers.fab.auth_manager.models.user attribute)": [[19, "airflow.providers.fab.auth_manager.models.User.fail_login_count"]], "first_name (airflow.providers.fab.auth_manager.models.registeruser attribute)": [[19, "airflow.providers.fab.auth_manager.models.RegisterUser.first_name"]], "first_name (airflow.providers.fab.auth_manager.models.user attribute)": [[19, "airflow.providers.fab.auth_manager.models.User.first_name"]], "get_full_name() (airflow.providers.fab.auth_manager.models.user method)": [[19, "airflow.providers.fab.auth_manager.models.User.get_full_name"]], "get_id() (airflow.providers.fab.auth_manager.models.user method)": [[19, "airflow.providers.fab.auth_manager.models.User.get_id"]], "get_name() (airflow.providers.fab.auth_manager.models.user method)": [[19, "airflow.providers.fab.auth_manager.models.User.get_name"]], "get_user_id() (airflow.providers.fab.auth_manager.models.user class method)": [[19, "airflow.providers.fab.auth_manager.models.User.get_user_id"]], "id (airflow.providers.fab.auth_manager.models.action attribute)": [[19, "airflow.providers.fab.auth_manager.models.Action.id"]], "id (airflow.providers.fab.auth_manager.models.permission attribute)": [[19, "airflow.providers.fab.auth_manager.models.Permission.id"]], "id (airflow.providers.fab.auth_manager.models.registeruser attribute)": [[19, "airflow.providers.fab.auth_manager.models.RegisterUser.id"]], "id (airflow.providers.fab.auth_manager.models.resource attribute)": [[19, "airflow.providers.fab.auth_manager.models.Resource.id"]], "id (airflow.providers.fab.auth_manager.models.role attribute)": [[19, "airflow.providers.fab.auth_manager.models.Role.id"]], "id (airflow.providers.fab.auth_manager.models.user attribute)": [[19, "airflow.providers.fab.auth_manager.models.User.id"]], "is_active (airflow.providers.fab.auth_manager.models.user property)": [[19, "airflow.providers.fab.auth_manager.models.User.is_active"]], "is_anonymous (airflow.providers.fab.auth_manager.models.user property)": [[19, "airflow.providers.fab.auth_manager.models.User.is_anonymous"]], "is_authenticated (airflow.providers.fab.auth_manager.models.user property)": [[19, "airflow.providers.fab.auth_manager.models.User.is_authenticated"]], "last_login (airflow.providers.fab.auth_manager.models.user attribute)": [[19, "airflow.providers.fab.auth_manager.models.User.last_login"]], "last_name (airflow.providers.fab.auth_manager.models.registeruser attribute)": [[19, "airflow.providers.fab.auth_manager.models.RegisterUser.last_name"]], "last_name (airflow.providers.fab.auth_manager.models.user attribute)": [[19, "airflow.providers.fab.auth_manager.models.User.last_name"]], "login_count (airflow.providers.fab.auth_manager.models.user attribute)": [[19, "airflow.providers.fab.auth_manager.models.User.login_count"]], "name (airflow.providers.fab.auth_manager.models.action attribute)": [[19, "airflow.providers.fab.auth_manager.models.Action.name"]], "name (airflow.providers.fab.auth_manager.models.resource attribute)": [[19, "airflow.providers.fab.auth_manager.models.Resource.name"]], "name (airflow.providers.fab.auth_manager.models.role attribute)": [[19, "airflow.providers.fab.auth_manager.models.Role.name"]], "password (airflow.providers.fab.auth_manager.models.registeruser attribute)": [[19, "airflow.providers.fab.auth_manager.models.RegisterUser.password"]], "password (airflow.providers.fab.auth_manager.models.user attribute)": [[19, "airflow.providers.fab.auth_manager.models.User.password"]], "permissions (airflow.providers.fab.auth_manager.models.role attribute)": [[19, "airflow.providers.fab.auth_manager.models.Role.permissions"]], "perms (airflow.providers.fab.auth_manager.models.user property)": [[19, "airflow.providers.fab.auth_manager.models.User.perms"]], "registration_date (airflow.providers.fab.auth_manager.models.registeruser attribute)": [[19, "airflow.providers.fab.auth_manager.models.RegisterUser.registration_date"]], "registration_hash (airflow.providers.fab.auth_manager.models.registeruser attribute)": [[19, "airflow.providers.fab.auth_manager.models.RegisterUser.registration_hash"]], "resource (airflow.providers.fab.auth_manager.models.permission attribute)": [[19, "airflow.providers.fab.auth_manager.models.Permission.resource"]], "resource_id (airflow.providers.fab.auth_manager.models.permission attribute)": [[19, "airflow.providers.fab.auth_manager.models.Permission.resource_id"]], "roles (airflow.providers.fab.auth_manager.models.user attribute)": [[19, "airflow.providers.fab.auth_manager.models.User.roles"]], "username (airflow.providers.fab.auth_manager.models.registeruser attribute)": [[19, "airflow.providers.fab.auth_manager.models.RegisterUser.username"]], "username (airflow.providers.fab.auth_manager.models.user attribute)": [[19, "airflow.providers.fab.auth_manager.models.User.username"]], "airflow.providers.fab.auth_manager.openapi": [[20, "module-airflow.providers.fab.auth_manager.openapi"]], "existing_roles (in module airflow.providers.fab.auth_manager.security_manager.constants)": [[21, "airflow.providers.fab.auth_manager.security_manager.constants.EXISTING_ROLES"]], "airflow.providers.fab.auth_manager.security_manager.constants": [[21, "module-airflow.providers.fab.auth_manager.security_manager.constants"]], "airflow.providers.fab.auth_manager.security_manager": [[22, "module-airflow.providers.fab.auth_manager.security_manager"]], "admin_permissions (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.ADMIN_PERMISSIONS"]], "dag_actions (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.DAG_ACTIONS"]], "dag_resources (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.DAG_RESOURCES"]], "fabairflowsecuritymanageroverride (class in airflow.providers.fab.auth_manager.security_manager.override)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride"]], "max_num_database_user_sessions (in module airflow.providers.fab.auth_manager.security_manager.override)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.MAX_NUM_DATABASE_USER_SESSIONS"]], "op_permissions (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.OP_PERMISSIONS"]], "role_configs (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.ROLE_CONFIGS"]], "user_permissions (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.USER_PERMISSIONS"]], "viewer_permissions (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.VIEWER_PERMISSIONS"]], "action_model (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.action_model"]], "actionmodelview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.actionmodelview"]], "add_homepage_access_to_custom_roles() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.add_homepage_access_to_custom_roles"]], "add_permission_to_role() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.add_permission_to_role"]], "add_permissions_menu() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.add_permissions_menu"]], "add_permissions_view() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.add_permissions_view"]], "add_register_user() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.add_register_user"]], "add_role() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.add_role"]], "add_user() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.add_user"]], "airflow.providers.fab.auth_manager.security_manager.override": [[23, "module-airflow.providers.fab.auth_manager.security_manager.override"]], "api_login_allow_multiple_providers (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.api_login_allow_multiple_providers"]], "auth_ldap_allow_self_signed (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_allow_self_signed"]], "auth_ldap_append_domain (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_append_domain"]], "auth_ldap_bind_first (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_bind_first"]], "auth_ldap_bind_password (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_bind_password"]], "auth_ldap_bind_user (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_bind_user"]], "auth_ldap_email_field (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_email_field"]], "auth_ldap_firstname_field (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_firstname_field"]], "auth_ldap_group_field (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_group_field"]], "auth_ldap_lastname_field (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_lastname_field"]], "auth_ldap_search (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_search"]], "auth_ldap_search_filter (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_search_filter"]], "auth_ldap_server (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_server"]], "auth_ldap_tls_cacertdir (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_tls_cacertdir"]], "auth_ldap_tls_cacertfile (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_tls_cacertfile"]], "auth_ldap_tls_certfile (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_tls_certfile"]], "auth_ldap_tls_demand (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_tls_demand"]], "auth_ldap_tls_keyfile (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_tls_keyfile"]], "auth_ldap_uid_field (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_uid_field"]], "auth_ldap_use_tls (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_use_tls"]], "auth_ldap_username_format (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_ldap_username_format"]], "auth_rate_limit (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_rate_limit"]], "auth_remote_user_env_var (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_remote_user_env_var"]], "auth_role_admin (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_role_admin"]], "auth_role_public (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_role_public"]], "auth_roles_mapping (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_roles_mapping"]], "auth_roles_sync_at_login (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_roles_sync_at_login"]], "auth_type (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_type"]], "auth_type_provider_name (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_type_provider_name"]], "auth_user_db() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_user_db"]], "auth_user_ldap() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_user_ldap"]], "auth_user_oauth() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_user_oauth"]], "auth_user_oid() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_user_oid"]], "auth_user_registration (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_user_registration"]], "auth_user_registration_role (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_user_registration_role"]], "auth_user_registration_role_jmespath (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_user_registration_role_jmespath"]], "auth_user_remote_user() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_user_remote_user"]], "auth_username_ci (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_username_ci"]], "auth_view (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.auth_view"]], "authdbview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.authdbview"]], "authldapview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.authldapview"]], "authoauthview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.authoauthview"]], "authoidview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.authoidview"]], "authremoteuserview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.authremoteuserview"]], "builtin_roles (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.builtin_roles"]], "bulk_sync_roles() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.bulk_sync_roles"]], "can_access_some_dags() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.can_access_some_dags"]], "check_authorization() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.check_authorization"]], "clean_perms() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.clean_perms"]], "count_users() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.count_users"]], "create_action() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.create_action"]], "create_admin_standalone() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.create_admin_standalone"]], "create_builtin_roles() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.create_builtin_roles"]], "create_dag_specific_permissions() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.create_dag_specific_permissions"]], "create_db() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.create_db"]], "create_jwt_manager() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.create_jwt_manager"]], "create_login_manager() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.create_login_manager"]], "create_perm_vm_for_all_dag() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.create_perm_vm_for_all_dag"]], "create_permission() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.create_permission"]], "create_resource() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.create_resource"]], "del_register_user() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.del_register_user"]], "delete_action() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.delete_action"]], "delete_permission() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.delete_permission"]], "delete_resource() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.delete_resource"]], "delete_role() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.delete_role"]], "filter_roles_by_perm_with_action() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.filter_roles_by_perm_with_action"]], "find_register_user() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.find_register_user"]], "find_role() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.find_role"]], "find_user() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.find_user"]], "get_accessible_dag_ids() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_accessible_dag_ids"]], "get_accessible_dags() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_accessible_dags"]], "get_action() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_action"]], "get_all_permissions() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_all_permissions"]], "get_all_resources() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_all_resources"]], "get_all_roles() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_all_roles"]], "get_all_users() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_all_users"]], "get_editable_dag_ids() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride static method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_editable_dag_ids"]], "get_editable_dags() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_editable_dags"]], "get_oauth_token_key_name() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_oauth_token_key_name"]], "get_oauth_token_secret_name() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_oauth_token_secret_name"]], "get_oauth_user_info() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_oauth_user_info"]], "get_oid_identity_url() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_oid_identity_url"]], "get_permission() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_permission"]], "get_public_role() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_public_role"]], "get_readable_dag_ids() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride static method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_readable_dag_ids"]], "get_readable_dags() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_readable_dags"]], "get_resource() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_resource"]], "get_resource_permissions() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_resource_permissions"]], "get_roles_from_keys() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_roles_from_keys"]], "get_session (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_session"]], "get_user_by_id() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_user_by_id"]], "get_user_menu_access() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_user_menu_access"]], "get_user_roles() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride static method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.get_user_roles"]], "init_role() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.init_role"]], "is_auth_limited (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.is_auth_limited"]], "is_dag_resource() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.is_dag_resource"]], "jwt_manager (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.jwt_manager"]], "ldap_extract() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride static method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.ldap_extract"]], "ldap_extract_list() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride static method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.ldap_extract_list"]], "load_user() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.load_user"]], "load_user_jwt() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.load_user_jwt"]], "log (in module airflow.providers.fab.auth_manager.security_manager.override)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.log"]], "oauth (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.oauth"]], "oauth_allow_list (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.oauth_allow_list"]], "oauth_providers (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.oauth_providers"]], "oauth_remotes (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.oauth_remotes"]], "oauth_token_getter() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride static method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.oauth_token_getter"]], "oauth_user_info (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.oauth_user_info"]], "oauth_user_info_getter() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.oauth_user_info_getter"]], "oauth_whitelists (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.oauth_whitelists"]], "oid (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.oid"]], "openid_providers (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride property)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.openid_providers"]], "permission_exists_in_one_or_more_roles() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.permission_exists_in_one_or_more_roles"]], "permission_model (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.permission_model"]], "permissionmodelview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.permissionmodelview"]], "perms_include_action() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.perms_include_action"]], "prefixed_dag_id() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.prefixed_dag_id"]], "register_views() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.register_views"]], "registeruser_model (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.registeruser_model"]], "registeruser_view (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.registeruser_view"]], "registeruserdbview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.registeruserdbview"]], "registerusermodelview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.registerusermodelview"]], "registeruseroauthview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.registeruseroauthview"]], "registeruseroidview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.registeruseroidview"]], "remove_permission_from_role() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.remove_permission_from_role"]], "reset_password() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.reset_password"]], "reset_user_sessions() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.reset_user_sessions"]], "resetmypasswordview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.resetmypasswordview"]], "resetpasswordview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.resetpasswordview"]], "resource_model (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.resource_model"]], "resourcemodelview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.resourcemodelview"]], "role_model (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.role_model"]], "rolemodelview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.rolemodelview"]], "security_cleanup() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.security_cleanup"]], "set_oauth_session() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.set_oauth_session"]], "sync_perm_for_dag() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.sync_perm_for_dag"]], "sync_resource_permissions() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.sync_resource_permissions"]], "sync_roles() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.sync_roles"]], "update_admin_permission() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.update_admin_permission"]], "update_role() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.update_role"]], "update_user() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.update_user"]], "update_user_auth_stat() (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride method)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.update_user_auth_stat"]], "user_model (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.user_model"]], "user_view (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.user_view"]], "userdbmodelview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.userdbmodelview"]], "userinfoeditview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.userinfoeditview"]], "userldapmodelview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.userldapmodelview"]], "useroauthmodelview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.useroauthmodelview"]], "useroidmodelview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.useroidmodelview"]], "userremoteusermodelview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.userremoteusermodelview"]], "userstatschartview (airflow.providers.fab.auth_manager.security_manager.override.fabairflowsecuritymanageroverride attribute)": [[23, "airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride.userstatschartview"]], "airflow.providers.fab.auth_manager.views": [[24, "module-airflow.providers.fab.auth_manager.views"]], "actionmodelview (class in airflow.providers.fab.auth_manager.views.permissions)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ActionModelView"]], "permissionpairmodelview (class in airflow.providers.fab.auth_manager.views.permissions)": [[25, "airflow.providers.fab.auth_manager.views.permissions.PermissionPairModelView"]], "resourcemodelview (class in airflow.providers.fab.auth_manager.views.permissions)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ResourceModelView"]], "add_title (airflow.providers.fab.auth_manager.views.permissions.actionmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ActionModelView.add_title"]], "add_title (airflow.providers.fab.auth_manager.views.permissions.permissionpairmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.PermissionPairModelView.add_title"]], "add_title (airflow.providers.fab.auth_manager.views.permissions.resourcemodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ResourceModelView.add_title"]], "airflow.providers.fab.auth_manager.views.permissions": [[25, "module-airflow.providers.fab.auth_manager.views.permissions"]], "base_permissions (airflow.providers.fab.auth_manager.views.permissions.actionmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ActionModelView.base_permissions"]], "base_permissions (airflow.providers.fab.auth_manager.views.permissions.permissionpairmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.PermissionPairModelView.base_permissions"]], "base_permissions (airflow.providers.fab.auth_manager.views.permissions.resourcemodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ResourceModelView.base_permissions"]], "class_permission_name (airflow.providers.fab.auth_manager.views.permissions.actionmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ActionModelView.class_permission_name"]], "class_permission_name (airflow.providers.fab.auth_manager.views.permissions.permissionpairmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.PermissionPairModelView.class_permission_name"]], "class_permission_name (airflow.providers.fab.auth_manager.views.permissions.resourcemodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ResourceModelView.class_permission_name"]], "edit_title (airflow.providers.fab.auth_manager.views.permissions.actionmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ActionModelView.edit_title"]], "edit_title (airflow.providers.fab.auth_manager.views.permissions.permissionpairmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.PermissionPairModelView.edit_title"]], "edit_title (airflow.providers.fab.auth_manager.views.permissions.resourcemodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ResourceModelView.edit_title"]], "label_columns (airflow.providers.fab.auth_manager.views.permissions.actionmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ActionModelView.label_columns"]], "label_columns (airflow.providers.fab.auth_manager.views.permissions.permissionpairmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.PermissionPairModelView.label_columns"]], "label_columns (airflow.providers.fab.auth_manager.views.permissions.resourcemodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ResourceModelView.label_columns"]], "list_columns (airflow.providers.fab.auth_manager.views.permissions.permissionpairmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.PermissionPairModelView.list_columns"]], "list_title (airflow.providers.fab.auth_manager.views.permissions.actionmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ActionModelView.list_title"]], "list_title (airflow.providers.fab.auth_manager.views.permissions.permissionpairmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.PermissionPairModelView.list_title"]], "list_title (airflow.providers.fab.auth_manager.views.permissions.resourcemodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ResourceModelView.list_title"]], "method_permission_name (airflow.providers.fab.auth_manager.views.permissions.actionmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ActionModelView.method_permission_name"]], "method_permission_name (airflow.providers.fab.auth_manager.views.permissions.permissionpairmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.PermissionPairModelView.method_permission_name"]], "method_permission_name (airflow.providers.fab.auth_manager.views.permissions.resourcemodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ResourceModelView.method_permission_name"]], "route_base (airflow.providers.fab.auth_manager.views.permissions.actionmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ActionModelView.route_base"]], "route_base (airflow.providers.fab.auth_manager.views.permissions.permissionpairmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.PermissionPairModelView.route_base"]], "route_base (airflow.providers.fab.auth_manager.views.permissions.resourcemodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ResourceModelView.route_base"]], "show_title (airflow.providers.fab.auth_manager.views.permissions.actionmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ActionModelView.show_title"]], "show_title (airflow.providers.fab.auth_manager.views.permissions.permissionpairmodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.PermissionPairModelView.show_title"]], "show_title (airflow.providers.fab.auth_manager.views.permissions.resourcemodelview attribute)": [[25, "airflow.providers.fab.auth_manager.views.permissions.ResourceModelView.show_title"]], "customrolemodelview (class in airflow.providers.fab.auth_manager.views.roles_list)": [[26, "airflow.providers.fab.auth_manager.views.roles_list.CustomRoleModelView"]], "airflow.providers.fab.auth_manager.views.roles_list": [[26, "module-airflow.providers.fab.auth_manager.views.roles_list"]], "base_permissions (airflow.providers.fab.auth_manager.views.roles_list.customrolemodelview attribute)": [[26, "airflow.providers.fab.auth_manager.views.roles_list.CustomRoleModelView.base_permissions"]], "class_permission_name (airflow.providers.fab.auth_manager.views.roles_list.customrolemodelview attribute)": [[26, "airflow.providers.fab.auth_manager.views.roles_list.CustomRoleModelView.class_permission_name"]], "method_permission_name (airflow.providers.fab.auth_manager.views.roles_list.customrolemodelview attribute)": [[26, "airflow.providers.fab.auth_manager.views.roles_list.CustomRoleModelView.method_permission_name"]], "customuserdbmodelview (class in airflow.providers.fab.auth_manager.views.user)": [[27, "airflow.providers.fab.auth_manager.views.user.CustomUserDBModelView"]], "customuserldapmodelview (class in airflow.providers.fab.auth_manager.views.user)": [[27, "airflow.providers.fab.auth_manager.views.user.CustomUserLDAPModelView"]], "customuseroauthmodelview (class in airflow.providers.fab.auth_manager.views.user)": [[27, "airflow.providers.fab.auth_manager.views.user.CustomUserOAuthModelView"]], "customuseroidmodelview (class in airflow.providers.fab.auth_manager.views.user)": [[27, "airflow.providers.fab.auth_manager.views.user.CustomUserOIDModelView"]], "customuserremoteusermodelview (class in airflow.providers.fab.auth_manager.views.user)": [[27, "airflow.providers.fab.auth_manager.views.user.CustomUserRemoteUserModelView"]], "multiresourceusermixin (class in airflow.providers.fab.auth_manager.views.user)": [[27, "airflow.providers.fab.auth_manager.views.user.MultiResourceUserMixin"]], "airflow.providers.fab.auth_manager.views.user": [[27, "module-airflow.providers.fab.auth_manager.views.user"]], "base_permissions (airflow.providers.fab.auth_manager.views.user.customuserdbmodelview attribute)": [[27, "airflow.providers.fab.auth_manager.views.user.CustomUserDBModelView.base_permissions"]], "base_permissions (airflow.providers.fab.auth_manager.views.user.customuserldapmodelview attribute)": [[27, "airflow.providers.fab.auth_manager.views.user.CustomUserLDAPModelView.base_permissions"]], "base_permissions (airflow.providers.fab.auth_manager.views.user.customuserremoteusermodelview attribute)": [[27, "airflow.providers.fab.auth_manager.views.user.CustomUserRemoteUserModelView.base_permissions"]], "base_permissions (airflow.providers.fab.auth_manager.views.user.multiresourceusermixin attribute)": [[27, "airflow.providers.fab.auth_manager.views.user.MultiResourceUserMixin.base_permissions"]], "class_permission_name (airflow.providers.fab.auth_manager.views.user.multiresourceusermixin property)": [[27, "airflow.providers.fab.auth_manager.views.user.MultiResourceUserMixin.class_permission_name"]], "class_permission_name_mapping (airflow.providers.fab.auth_manager.views.user.customuserdbmodelview attribute)": [[27, "airflow.providers.fab.auth_manager.views.user.CustomUserDBModelView.class_permission_name_mapping"]], "class_permission_name_mapping (airflow.providers.fab.auth_manager.views.user.customuserldapmodelview attribute)": [[27, "airflow.providers.fab.auth_manager.views.user.CustomUserLDAPModelView.class_permission_name_mapping"]], "class_permission_name_mapping (airflow.providers.fab.auth_manager.views.user.customuserremoteusermodelview attribute)": [[27, "airflow.providers.fab.auth_manager.views.user.CustomUserRemoteUserModelView.class_permission_name_mapping"]], "class_permission_name_mapping (airflow.providers.fab.auth_manager.views.user.multiresourceusermixin attribute)": [[27, "airflow.providers.fab.auth_manager.views.user.MultiResourceUserMixin.class_permission_name_mapping"]], "method_permission_name (airflow.providers.fab.auth_manager.views.user.customuserdbmodelview attribute)": [[27, "airflow.providers.fab.auth_manager.views.user.CustomUserDBModelView.method_permission_name"]], "method_permission_name (airflow.providers.fab.auth_manager.views.user.customuserldapmodelview attribute)": [[27, "airflow.providers.fab.auth_manager.views.user.CustomUserLDAPModelView.method_permission_name"]], "method_permission_name (airflow.providers.fab.auth_manager.views.user.customuserremoteusermodelview attribute)": [[27, "airflow.providers.fab.auth_manager.views.user.CustomUserRemoteUserModelView.method_permission_name"]], "method_permission_name (airflow.providers.fab.auth_manager.views.user.multiresourceusermixin attribute)": [[27, "airflow.providers.fab.auth_manager.views.user.MultiResourceUserMixin.method_permission_name"]], "show() (airflow.providers.fab.auth_manager.views.user.multiresourceusermixin method)": [[27, "airflow.providers.fab.auth_manager.views.user.MultiResourceUserMixin.show"]], "customresetmypasswordview (class in airflow.providers.fab.auth_manager.views.user_edit)": [[28, "airflow.providers.fab.auth_manager.views.user_edit.CustomResetMyPasswordView"]], "customresetpasswordview (class in airflow.providers.fab.auth_manager.views.user_edit)": [[28, "airflow.providers.fab.auth_manager.views.user_edit.CustomResetPasswordView"]], "customuserinfoeditview (class in airflow.providers.fab.auth_manager.views.user_edit)": [[28, "airflow.providers.fab.auth_manager.views.user_edit.CustomUserInfoEditView"]], "airflow.providers.fab.auth_manager.views.user_edit": [[28, "module-airflow.providers.fab.auth_manager.views.user_edit"]], "base_permissions (airflow.providers.fab.auth_manager.views.user_edit.customresetmypasswordview attribute)": [[28, "airflow.providers.fab.auth_manager.views.user_edit.CustomResetMyPasswordView.base_permissions"]], "base_permissions (airflow.providers.fab.auth_manager.views.user_edit.customresetpasswordview attribute)": [[28, "airflow.providers.fab.auth_manager.views.user_edit.CustomResetPasswordView.base_permissions"]], "base_permissions (airflow.providers.fab.auth_manager.views.user_edit.customuserinfoeditview attribute)": [[28, "airflow.providers.fab.auth_manager.views.user_edit.CustomUserInfoEditView.base_permissions"]], "class_permission_name (airflow.providers.fab.auth_manager.views.user_edit.customresetmypasswordview attribute)": [[28, "airflow.providers.fab.auth_manager.views.user_edit.CustomResetMyPasswordView.class_permission_name"]], "class_permission_name (airflow.providers.fab.auth_manager.views.user_edit.customresetpasswordview attribute)": [[28, "airflow.providers.fab.auth_manager.views.user_edit.CustomResetPasswordView.class_permission_name"]], "class_permission_name (airflow.providers.fab.auth_manager.views.user_edit.customuserinfoeditview attribute)": [[28, "airflow.providers.fab.auth_manager.views.user_edit.CustomUserInfoEditView.class_permission_name"]], "method_permission_name (airflow.providers.fab.auth_manager.views.user_edit.customresetmypasswordview attribute)": [[28, "airflow.providers.fab.auth_manager.views.user_edit.CustomResetMyPasswordView.method_permission_name"]], "method_permission_name (airflow.providers.fab.auth_manager.views.user_edit.customresetpasswordview attribute)": [[28, "airflow.providers.fab.auth_manager.views.user_edit.CustomResetPasswordView.method_permission_name"]], "method_permission_name (airflow.providers.fab.auth_manager.views.user_edit.customuserinfoeditview attribute)": [[28, "airflow.providers.fab.auth_manager.views.user_edit.CustomUserInfoEditView.method_permission_name"]], "route_base (airflow.providers.fab.auth_manager.views.user_edit.customuserinfoeditview attribute)": [[28, "airflow.providers.fab.auth_manager.views.user_edit.CustomUserInfoEditView.route_base"]], "customuserstatschartview (class in airflow.providers.fab.auth_manager.views.user_stats)": [[29, "airflow.providers.fab.auth_manager.views.user_stats.CustomUserStatsChartView"]], "airflow.providers.fab.auth_manager.views.user_stats": [[29, "module-airflow.providers.fab.auth_manager.views.user_stats"]], "base_permissions (airflow.providers.fab.auth_manager.views.user_stats.customuserstatschartview attribute)": [[29, "airflow.providers.fab.auth_manager.views.user_stats.CustomUserStatsChartView.base_permissions"]], "class_permission_name (airflow.providers.fab.auth_manager.views.user_stats.customuserstatschartview attribute)": [[29, "airflow.providers.fab.auth_manager.views.user_stats.CustomUserStatsChartView.class_permission_name"]], "method_permission_name (airflow.providers.fab.auth_manager.views.user_stats.customuserstatschartview attribute)": [[29, "airflow.providers.fab.auth_manager.views.user_stats.CustomUserStatsChartView.method_permission_name"]], "route_base (airflow.providers.fab.auth_manager.views.user_stats.customuserstatschartview attribute)": [[29, "airflow.providers.fab.auth_manager.views.user_stats.CustomUserStatsChartView.route_base"]], "__version__ (in module airflow.providers.fab)": [[30, "airflow.providers.fab.__version__"]], "airflow.providers.fab": [[30, "module-airflow.providers.fab"]]}}) \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/security.html b/docs-archive/apache-airflow-providers-fab/1.0.4/security.html new file mode 100644 index 00000000000..334dfaaf265 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/security.html @@ -0,0 +1,885 @@ + + + + + + + + + + + + Releasing security patches — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+
+
+

Releasing security patches

+

Airflow providers are released independently from Airflow itself and the information about vulnerabilities +is published separately. You can upgrade providers independently from Airflow itself, following the +instructions found in Installation from PyPI.

+

When we release Provider version, the development is always done from the main branch where we prepare +the next version. The provider uses strict SemVer versioning policy. Depending on +the scope of the change, Provider will get ‘’MAJOR’’ version upgrade when there are +breaking changes, MINOR version upgrade when there are new features or PATCHLEVEL version upgrade +when there are only bug fixes (including security bugfixes) - and this is the only version that receives +security fixes by default, so you should upgrade to latest version of the provider if you want to receive +all released security fixes.

+

The only exception to that rule is when we have a critical security fix and good reason to provide an +out-of-band release for the provider, in which case stakeholders in the provider might decide to cherry-pick +and prepare a branch for an older version of the provider following the +mixed governance model +and requires interested parties to cherry-pick and test the fixes.

+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/1.0.4/stable-rest-api-ref.html b/docs-archive/apache-airflow-providers-fab/1.0.4/stable-rest-api-ref.html new file mode 100644 index 00000000000..9af5df8eeb0 --- /dev/null +++ b/docs-archive/apache-airflow-providers-fab/1.0.4/stable-rest-api-ref.html @@ -0,0 +1,870 @@ + + + + + + + + + + + + REST API Reference — apache-airflow-providers-fab Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+
+
+

REST API Reference

+

It’s a stub file. It will be converted automatically during the build process +to the valid documentation by the Sphinx plugin. See: /docs/conf.py

+
+ + + +
+ +
+
+
+
+
+

Was this entry helpful?

+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-archive/apache-airflow-providers-fab/stable.txt b/docs-archive/apache-airflow-providers-fab/stable.txt index e4c0d46e55f..a6a3a43c3a0 100644 --- a/docs-archive/apache-airflow-providers-fab/stable.txt +++ b/docs-archive/apache-airflow-providers-fab/stable.txt @@ -1 +1 @@ -1.0.3 \ No newline at end of file +1.0.4 \ No newline at end of file
+ + +