Repository: great-expectations/great_expectations

Issue:
UpdateDataDocsAction ignores site_names parameter
**Describe the bug**
When creating data docs sites, the UpdateDataDocsAction ignores the site_names parameter and tries to build all sites anyway. It also tries to get urls for all sites. This leads to errors when sites may not be accessible. For example, some users use the following pattern to identify an active site depending on the environment (e.g. dev / prod):
```
    - name: update_data_docs
      action:
        class_name: UpdateDataDocsAction
        site_names:
          - ${ACTIVE_SITE}
```

**To Reproduce**
1. Create 2 data docs sites, one that you can connect to (e.g. `local_site`) and one you cannot (e.g. make up an invalid s3 bucket).
2. set the site_names parameter to the site you can connect to
3. see the errors from Great Expectations trying to connect to the invalid site

**Expected behavior**
I expect Great Expectations to not attempt to connect to sites not listed in the site_names parameter.

**Environment (please complete the following information):**
 - OS: osx 10.15.6
 - GE Version: 0.12.4

**Additional context**
See also this thread: https://greatexpectationstalk.slack.com/archives/CUTCNHN82/p1602782817160500



Discussion:

Resolving patch:
diff --git a/great_expectations/data_context/data_context.py b/great_expectations/data_context/data_context.py
--- a/great_expectations/data_context/data_context.py
+++ b/great_expectations/data_context/data_context.py
@@ -510,6 +510,7 @@ def get_docs_sites_urls(
         resource_identifier=None,
         site_name: Optional[str] = None,
         only_if_exists=True,
+        site_names: Optional[List[str]] = None,
     ) -> List[Dict[str, str]]:
         """
         Get URLs for a resource for all data docs sites.
@@ -524,12 +525,24 @@ def get_docs_sites_urls(
                 the URLs of the index page.
             site_name: Optionally specify which site to open. If not specified,
                 return all urls in the project.
+            site_names: Optionally specify which sites are active. Sites not in
+                this list are not processed, even if specified in site_name.
 
         Returns:
             list: a list of URLs. Each item is the URL for the resource for a
                 data docs site
         """
-        sites = self._project_config_with_variables_substituted.data_docs_sites
+        unfiltered_sites = (
+            self._project_config_with_variables_substituted.data_docs_sites
+        )
+
+        # Filter out sites that are not in site_names
+        sites = (
+            {k: v for k, v in unfiltered_sites.items() if k in site_names}
+            if site_names
+            else unfiltered_sites
+        )
+
         if not sites:
             logger.debug("Found no data_docs_sites.")
             return []
@@ -1548,7 +1561,7 @@ def build_data_docs(
             for site_name, site_config in sites.items():
                 logger.debug("Building Data Docs Site %s" % site_name,)
 
-                if (site_names and site_name in site_names) or not site_names:
+                if (site_names and (site_name in site_names)) or not site_names:
                     complete_site_config = site_config
                     module_name = "great_expectations.render.renderer.site_builder"
                     site_builder = instantiate_class_from_config(
diff --git a/great_expectations/validation_operators/actions.py b/great_expectations/validation_operators/actions.py
--- a/great_expectations/validation_operators/actions.py
+++ b/great_expectations/validation_operators/actions.py
@@ -38,7 +38,7 @@ def run(
         validation_result_suite,
         validation_result_suite_identifier,
         data_asset,
-        **kwargs
+        **kwargs,
     ):
         """
 
@@ -52,7 +52,7 @@ def run(
             validation_result_suite,
             validation_result_suite_identifier,
             data_asset,
-            **kwargs
+            **kwargs,
         )
 
     def _run(
@@ -211,9 +211,7 @@ def __init__(
         """
         super().__init__(data_context)
         if not pypd:
-            raise DataContextError(
-                "ModuleNotFoundError: No module named 'pypd'"
-            )
+            raise DataContextError("ModuleNotFoundError: No module named 'pypd'")
         self.api_key = api_key
         assert api_key, "No Pagerduty api_key found in action config."
         self.routing_key = routing_key
@@ -254,16 +252,18 @@ def _run(
                 "expectation_suite_name", "__no_expectation_suite_name__"
             )
             pypd.api_key = self.api_key
-            pypd.EventV2.create(data={
-                "routing_key": self.routing_key,
-                "dedup_key": expectation_suite_name,
-                "event_action": "trigger",
-                "payload": {
-                    "summary": f"Great Expectations suite check {expectation_suite_name} has failed",
-                    "severity": "critical",
-                    "source": "Great Expectations",
+            pypd.EventV2.create(
+                data={
+                    "routing_key": self.routing_key,
+                    "dedup_key": expectation_suite_name,
+                    "event_action": "trigger",
+                    "payload": {
+                        "summary": f"Great Expectations suite check {expectation_suite_name} has failed",
+                        "severity": "critical",
+                        "source": "Great Expectations",
+                    },
                 }
-            })
+            )
 
             return {"pagerduty_alert_result": "success"}
         return {"pagerduty_alert_result": "none sent"}
@@ -538,7 +538,8 @@ def _run(
 
         # get the URL for the validation result
         docs_site_urls_list = self.data_context.get_docs_sites_urls(
-            resource_identifier=validation_result_suite_identifier
+            resource_identifier=validation_result_suite_identifier,
+            site_names=self._site_names,
         )
         # process payload
         data_docs_validation_results = {}


Test patch: