olegkachur-e commented on code in PR #74753:
URL: https://github.com/apache/airflow/pull/74753#discussion_r4324755649


##########
providers/google/src/airflow/providers/google/cloud/operators/dataproc.py:
##########
@@ -117,6 +118,204 @@ class InstanceFlexibilityPolicy:
     instance_selection_list: list[InstanceSelection]
 
 
+class HardwareClass(Enum):
+    """
+    Hardware class of a High Obtainability (HO) mode instance group.
+
+    Representation for
+    
google.cloud.dataproc.v1#google.cloud.dataproc.v1.FlexibleInstanceGroupConfig.HardwareClass.
+    """
+
+    STANDARD = "STANDARD"
+    PERFORMANCE = "PERFORMANCE"
+
+
+FLEXIBLE_CONFIG_ALLOWED_CORE_COUNTS = (2, 4, 8, 16, 32)
+
+
+@dataclass
+class FlexibleInstanceGroupConfig:

Review Comment:
   Why don't we use just the native 
google.cloud.dataproc.v1#google.cloud.dataproc.v1.FlexibleInstanceGroupConfig 
type? It seems it has all the functionality and validation needed? 



##########
providers/google/src/airflow/providers/google/cloud/operators/dataproc.py:
##########
@@ -652,7 +851,24 @@ class 
DataprocCreateClusterOperator(GoogleCloudBaseOperator):
         values to parameter of DataprocCreateCluster operator.
     :param cluster_config: Required. The cluster config to create.
         If a dict is provided, it must be of the same form as the protobuf 
message
-        :class:`~google.cloud.dataproc_v1.types.ClusterConfig`
+        :class:`~google.cloud.dataproc_v1.types.ClusterConfig`.

Review Comment:
   I don't think it's a good place for this text here, since ClusterConfig has 
a lot of ways to be specified (and expanding), and all of them are referenced 
in the proto and docs).



##########
providers/google/tests/system/google/cloud/dataproc/example_dataproc_cluster_high_obtainability.py:
##########
@@ -0,0 +1,172 @@
+#
+# 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.
+"""Example Airflow DAG for a Dataproc High Obtainability (HO) mode cluster.
+
+In High Obtainability mode node groups are described by abstract requirements
+(``FlexibleInstanceGroupConfig``: number of instances, core count and hardware
+class) instead of concrete machine types. Dataproc resolves them into a ranked
+list of widely available machine families to minimize stockouts. HO clusters
+are always auto-zoned.
+
+The DAG creates an HO cluster, scales its primary workers through the
+authoritative ``config.worker_flexible_config.num_instances`` update path,
+scales the secondary workers through the legacy
+``config.secondary_worker_config.num_instances`` compatibility path (which the
+API keeps accepting for HO clusters), submits a Spark job and deletes the
+cluster.
+"""
+
+from __future__ import annotations
+
+import os
+from datetime import datetime
+
+from airflow.models.dag import DAG
+from airflow.providers.google.cloud.operators.dataproc import (
+    DataprocCreateClusterOperator,
+    DataprocDeleteClusterOperator,
+    DataprocSubmitJobOperator,
+    DataprocUpdateClusterOperator,
+    FlexibleInstanceGroupConfig,
+    flexible_scale_cluster_update,
+)
+
+try:
+    from airflow.sdk import TriggerRule
+except ImportError:
+    # Compatibility for Airflow < 3.1
+    from airflow.utils.trigger_rule import TriggerRule  # type: 
ignore[no-redef,attr-defined]
+
+from system.google import DEFAULT_GCP_SYSTEM_TEST_PROJECT_ID
+
+ENV_ID = os.environ.get("SYSTEM_TESTS_ENV_ID", "default")
+DAG_ID = "dataproc_cluster_high_obtainability"
+PROJECT_ID = os.environ.get("SYSTEM_TESTS_GCP_PROJECT") or 
DEFAULT_GCP_SYSTEM_TEST_PROJECT_ID
+
+CLUSTER_NAME_BASE = f"cluster-{DAG_ID}".replace("_", "-")
+CLUSTER_NAME_FULL = CLUSTER_NAME_BASE + f"-{ENV_ID}".replace("_", "-")
+CLUSTER_NAME = CLUSTER_NAME_BASE if len(CLUSTER_NAME_FULL) >= 33 else 
CLUSTER_NAME_FULL
+REGION = "us-central1"
+
+# [START how_to_cloud_dataproc_create_ho_cluster_config]
+# Note: no machine types, disk types or zone are specified. HO clusters are
+# cluster-wide: master and primary workers must both use a flexible config.
+HO_CLUSTER_CONFIG = {

Review Comment:
   Can we minimize resources needed to demonstrate functionality?  
   
   It will be a positive thing for a community members to run, and for regular 
tests suite CI runs as well. 
   
   For example: 
   
   ```
   HO_CLUSTER_CONFIG = {
       "master_flexible_config": {
           "num_instances": 1,
           "core_count": 2,
           "hardware_class": "STANDARD",
           "boot_disk_size_gb": 32,
       },
       "worker_flexible_config": {
           "num_instances": 2,
           "core_count": 2,
           "hardware_class": "STANDARD",
           "boot_disk_size_gb": 32,
       },
       "secondary_worker_flexible_config": {
           "num_instances": 1,
           "core_count": 2,
           "hardware_class": "STANDARD",
           "boot_disk_size_gb": 32,
       },
   }
   ```
   
   And for the update:
   
   ```
   cluster={
       "config": {
           "worker_flexible_config": {"num_instances": 3},
           "secondary_worker_flexible_config": {"num_instances": 0},
       }
   },
   update_mask={
       "paths": [
           "config.worker_flexible_config.num_instances",
           "config.secondary_worker_flexible_config.num_instances",
       ]
   },
   ```
   
   
   



##########
providers/google/docs/operators/cloud/dataproc.rst:
##########
@@ -186,6 +186,44 @@ You can use deferrable mode for this action in order to 
run the operator asynchr
     :start-after: [START how_to_cloud_dataproc_create_cluster_operator_async]
     :end-before: [END how_to_cloud_dataproc_create_cluster_operator_async]
 
+High Obtainability (HO) mode clusters
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+High Obtainability (HO) mode enables creating Dataproc clusters using abstract 
hardware requirements

Review Comment:
   Id' love to see the link to the official google docs as well (if available).



##########
providers/google/tests/system/google/cloud/dataproc/example_dataproc_cluster_high_obtainability.py:
##########
@@ -0,0 +1,172 @@
+#
+# 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.
+"""Example Airflow DAG for a Dataproc High Obtainability (HO) mode cluster.
+
+In High Obtainability mode node groups are described by abstract requirements
+(``FlexibleInstanceGroupConfig``: number of instances, core count and hardware
+class) instead of concrete machine types. Dataproc resolves them into a ranked
+list of widely available machine families to minimize stockouts. HO clusters
+are always auto-zoned.
+
+The DAG creates an HO cluster, scales its primary workers through the
+authoritative ``config.worker_flexible_config.num_instances`` update path,
+scales the secondary workers through the legacy
+``config.secondary_worker_config.num_instances`` compatibility path (which the
+API keeps accepting for HO clusters), submits a Spark job and deletes the
+cluster.
+"""
+
+from __future__ import annotations
+
+import os
+from datetime import datetime
+
+from airflow.models.dag import DAG
+from airflow.providers.google.cloud.operators.dataproc import (
+    DataprocCreateClusterOperator,
+    DataprocDeleteClusterOperator,
+    DataprocSubmitJobOperator,
+    DataprocUpdateClusterOperator,
+    FlexibleInstanceGroupConfig,
+    flexible_scale_cluster_update,
+)
+
+try:
+    from airflow.sdk import TriggerRule
+except ImportError:
+    # Compatibility for Airflow < 3.1
+    from airflow.utils.trigger_rule import TriggerRule  # type: 
ignore[no-redef,attr-defined]
+
+from system.google import DEFAULT_GCP_SYSTEM_TEST_PROJECT_ID
+
+ENV_ID = os.environ.get("SYSTEM_TESTS_ENV_ID", "default")
+DAG_ID = "dataproc_cluster_high_obtainability"
+PROJECT_ID = os.environ.get("SYSTEM_TESTS_GCP_PROJECT") or 
DEFAULT_GCP_SYSTEM_TEST_PROJECT_ID
+
+CLUSTER_NAME_BASE = f"cluster-{DAG_ID}".replace("_", "-")
+CLUSTER_NAME_FULL = CLUSTER_NAME_BASE + f"-{ENV_ID}".replace("_", "-")
+CLUSTER_NAME = CLUSTER_NAME_BASE if len(CLUSTER_NAME_FULL) >= 33 else 
CLUSTER_NAME_FULL
+REGION = "us-central1"
+
+# [START how_to_cloud_dataproc_create_ho_cluster_config]
+# Note: no machine types, disk types or zone are specified. HO clusters are
+# cluster-wide: master and primary workers must both use a flexible config.
+HO_CLUSTER_CONFIG = {
+    "master_flexible_config": FlexibleInstanceGroupConfig(
+        num_instances=1, core_count=4, hardware_class="STANDARD"
+    ),
+    # A plain dict with the same keys is accepted as well.
+    "worker_flexible_config": {
+        "num_instances": 2,
+        "core_count": 8,
+        "hardware_class": "PERFORMANCE",
+        "boot_disk_size_gb": 500,
+    },
+    "secondary_worker_flexible_config": {
+        "num_instances": 1,
+        "core_count": 8,
+        "hardware_class": "PERFORMANCE",
+    },
+    "software_config": {
+        "image_version": "2.2",
+    },
+}
+# [END how_to_cloud_dataproc_create_ho_cluster_config]
+
+SPARK_PI_JOB = {
+    "reference": {"project_id": PROJECT_ID},
+    "placement": {"cluster_name": CLUSTER_NAME},
+    "spark_job": {
+        "main_class": "org.apache.spark.examples.SparkPi",
+        "jar_file_uris": 
["file:///usr/lib/spark/examples/jars/spark-examples.jar"],
+        "args": ["10"],
+    },
+}
+
+with DAG(

Review Comment:
   Can you please share the result of the DAG execution?



##########
providers/google/pyproject.toml:
##########
@@ -104,7 +104,7 @@ dependencies = [
     "google-cloud-dataflow-client>=0.12.0",
     "google-cloud-dataform>=0.10.0",
     "google-cloud-dataplex>=2.18.0",
-    "google-cloud-dataproc>=5.27.0",
+    "google-cloud-dataproc>=5.32.0",

Review Comment:
   I think the uv.lock update should follow on the version bump.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to