czy006 commented on code in PR #3072:
URL: https://github.com/apache/amoro/pull/3072#discussion_r1719222612


##########
amoro-ams/amoro-ams-server/src/test/resources/config.yaml:
##########
@@ -0,0 +1,235 @@
+#
+# 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.
+#
+
+ams:
+  admin-username: admin
+  admin-password: admin
+  server-bind-host: "0.0.0.0"
+  server-expose-host: "127.0.0.1"
+
+  thrift-server:
+    max-message-size: 104857600 # 100MB
+    selector-thread-count: 2
+    selector-queue-size: 4
+    table-service:
+      bind-port: 1260
+      worker-thread-count: 20
+    optimizing-service:
+      bind-port: 1261
+
+  http-server:
+    bind-port: 1630
+
+  refresh-external-catalogs:
+    interval: 180000 # 3min
+    thread-count: 10
+    queue-size: 1000000
+
+  refresh-tables:
+    thread-count: 10
+    interval: 60000 # 1min
+
+  self-optimizing:
+    commit-thread-count: 10
+    runtime-data-keep-days: 30
+    runtime-data-expire-interval-hours: 1
+
+  optimizer:
+    heart-beat-timeout: 60000 # 1min
+    task-ack-timeout: 30000 # 30s
+    polling-timeout: 3000 # 3s
+    max-planning-parallelism: 1 # default 1
+
+  blocker:
+    timeout: 60000 # 1min
+
+  # optional features
+  expire-snapshots:
+    enabled: true
+    thread-count: 10
+
+  clean-orphan-files:
+    enabled: true
+    thread-count: 10
+
+  clean-dangling-delete-files:
+    enabled: true
+    thread-count: 10
+
+  sync-hive-tables:
+    enabled: true
+    thread-count: 10
+
+  data-expiration:
+    enabled: false
+    thread-count: 10
+    interval: 1d
+
+  auto-create-tags:
+    enabled: true
+    thread-count: 3
+    interval: 60000 # 1min
+
+  database:
+    type: derby
+    jdbc-driver-class: org.apache.derby.jdbc.EmbeddedDriver
+    url: jdbc:derby:/tmp/amoro/derby;create=true
+    connection-pool-max-total: 20
+    connection-pool-max-idle: 16
+    connection-pool-max-wait-millis: 1000
+
+#    MySQL database configuration.
+#    database:
+#      type: mysql
+#      jdbc-driver-class: com.mysql.cj.jdbc.Driver
+#      url: 
jdbc:mysql://127.0.0.1:3306/db?useUnicode=true&characterEncoding=UTF8&autoReconnect=true&useAffectedRows=true&allowPublicKeyRetrieval=true&useSSL=false
+#      username: root
+#      password: root
+#      connection-pool-max-total: 20
+#      connection-pool-max-idle: 16
+#      connection-pool-max-wait-millis: 1000
+
+  #  Postgres database configuration.
+  #  database:
+  #    type: postgres
+  #    jdbc-driver-class: org.postgresql.Driver
+  #    url: jdbc:postgresql://127.0.0.1:5432/db
+  #    username: user
+  #    password: passwd
+  #    connection-pool-max-total: 20
+  #    connection-pool-max-idle: 16
+  #    connection-pool-max-wait-millis: 1000
+
+  terminal:
+    backend: local
+    local.spark.sql.iceberg.handle-timestamp-without-timezone: false
+
+#  Kyuubi terminal backend configuration.
+#  terminal:
+#    backend: kyuubi
+#    kyuubi.jdbc.url: jdbc:hive2://127.0.0.1:10009/
+
+#  High availability configuration.
+#  ha:
+#    enabled: true
+#    cluster-name: default
+#    zookeeper-address: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183
+
+
+containers:
+  - name: localContainer
+    container-impl: org.apache.amoro.server.manager.LocalOptimizerContainer
+    properties:
+      export.JAVA_HOME: "/opt/java"   # JDK environment
+
+  - name: sparkContainer
+    container-impl: org.apache.amoro.server.manager.SparkOptimizerContainer
+    properties:
+      spark-home: /opt/spark/                                     # Spark 
install home
+      master: yarn                                                # The 
cluster manager to connect to. See the list of 
https://spark.apache.org/docs/latest/submitting-applications.html#master-urls.
+      deploy-mode: cluster                                        # Spark 
deploy mode, client or cluster
+      export.JVM_ARGS: -Djava.security.krb5.conf=/opt/krb5.conf   # Spark 
launch jvm args, like kerberos config when ues kerberos
+      export.HADOOP_CONF_DIR: /etc/hadoop/conf/                   # Hadoop 
config dir
+      export.HADOOP_USER_NAME: hadoop                             # Hadoop 
user submit on yarn
+      export.SPARK_CONF_DIR: /opt/spark/conf/                     # Spark 
config dir
+      # spark kubernetes application properties.
+      job-uri: "local:///opt/spark/usrlib/optimizer-job.jar"      # Optimizer 
job main jar for kubernetes application
+      ams-optimizing-uri: thrift://ams.amoro.service.local:1261   # AMS 
optimizing uri
+      spark-conf.spark.dynamicAllocation.enabled: "true"          # Enabling 
DRA feature can make full use of computing resources
+      spark-conf.spark.shuffle.service.enabled: "false"           # If spark 
DRA is used on kubernetes, we should set it false
+      spark-conf.spark.dynamicAllocation.shuffleTracking.enabled: "true"       
                   # Enables shuffle file tracking for executors, which allows 
dynamic allocation without the need for an external shuffle service
+      spark-conf.spark.kubernetes.container.image: 
"apache/amoro-spark-optimizer:{version}"       # Optimizer image ref
+      spark-conf.spark.kubernetes.namespace: <spark-namespace>                 
                   # Namespace that is used within kubernetes cluster
+      spark-conf.spark.kubernetes.authenticate.driver.serviceAccountName: 
<spark-sa>              # Service account that is used within kubernetes 
cluster.
+
+
+  - name: KubernetesContainer
+    container-impl: 
org.apache.amoro.server.manager.KubernetesOptimizerContainer
+    properties:
+      kube-config-path: /Users/wyx/.kube/config
+#      kube-config-path: "~/.kube/config"
+      image: apache/amoro:0.7-SNAPSHOT
+      namespace: default
+      pullPolicy: "IfNotPresent"
+      podTemplate: |
+        apiVersion: apps/v1
+        kind: PodTemplate
+        metadata:
+          name: <NAME_PREFIX><resourceId>
+        template:
+          metadata:
+            labels:
+              app: <NAME_PREFIX><resourceId>
+              AmoroOptimizerGroup: <groupName>
+              AmoroResourceId: <resourceId>
+          spec:
+            containers:
+              - name: optimizer
+                image: apache/amoro:0.7-SNAPSHOT
+                imagePullPolicy: IfNotPresent
+                command: [ "sh", "-c", "<startUpArgs>" ]
+                resources:
+                  limits:

Review Comment:
   We need to fill in some specific parameter values ​​for testing instead of 
leaving them blank



##########
amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/manager/TestKubernetesOptimizerContainer.java:
##########
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+
+package org.apache.amoro.server.manager;
+
+import io.fabric8.kubernetes.api.model.LocalObjectReference;
+import io.fabric8.kubernetes.api.model.LocalObjectReferenceBuilder;
+import io.fabric8.kubernetes.api.model.PodTemplate;
+import io.fabric8.kubernetes.api.model.Quantity;
+import io.fabric8.kubernetes.api.model.apps.Deployment;
+import org.apache.amoro.api.OptimizerProperties;
+import org.apache.amoro.api.resource.Resource;
+import org.apache.amoro.api.resource.ResourceType;
+import org.apache.amoro.server.AmoroManagementConf;
+import org.apache.amoro.shade.guava32.com.google.common.base.Preconditions;
+import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
+import org.apache.amoro.shade.jackson2.com.fasterxml.jackson.databind.JsonNode;
+import 
org.apache.amoro.shade.jackson2.com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.amoro.utils.JacksonUtil;
+import org.junit.Assert;
+import org.junit.Test;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class TestKubernetesOptimizerContainer {
+  KubernetesOptimizerContainer kubernetesOptimizerContainer = new 
KubernetesOptimizerContainer();
+  Map<String, String> containerProperties = Maps.newHashMap();
+  public static final String MEMORY_PROPERTY = "memory";
+  public static final String CPU_FACTOR_PROPERTY = "cpu.factor";
+  public static final String IMAGE = "image";
+  public static final String PULL_POLICY = "pullPolicy";
+  public static final String PULL_SECRETS = "imagePullSecrets";
+
+  public TestKubernetesOptimizerContainer() throws IOException {

Review Comment:
   can use junit `@Before` to init config file or other



##########
amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/manager/TestKubernetesOptimizerContainer.java:
##########
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+
+package org.apache.amoro.server.manager;
+
+import io.fabric8.kubernetes.api.model.LocalObjectReference;
+import io.fabric8.kubernetes.api.model.LocalObjectReferenceBuilder;
+import io.fabric8.kubernetes.api.model.PodTemplate;
+import io.fabric8.kubernetes.api.model.Quantity;
+import io.fabric8.kubernetes.api.model.apps.Deployment;
+import org.apache.amoro.api.OptimizerProperties;
+import org.apache.amoro.api.resource.Resource;
+import org.apache.amoro.api.resource.ResourceType;
+import org.apache.amoro.server.AmoroManagementConf;
+import org.apache.amoro.shade.guava32.com.google.common.base.Preconditions;
+import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
+import org.apache.amoro.shade.jackson2.com.fasterxml.jackson.databind.JsonNode;
+import 
org.apache.amoro.shade.jackson2.com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.amoro.utils.JacksonUtil;
+import org.junit.Assert;
+import org.junit.Test;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class TestKubernetesOptimizerContainer {
+  KubernetesOptimizerContainer kubernetesOptimizerContainer = new 
KubernetesOptimizerContainer();
+  Map<String, String> containerProperties = Maps.newHashMap();
+  public static final String MEMORY_PROPERTY = "memory";
+  public static final String CPU_FACTOR_PROPERTY = "cpu.factor";
+  public static final String IMAGE = "image";
+  public static final String PULL_POLICY = "pullPolicy";
+  public static final String PULL_SECRETS = "imagePullSecrets";
+
+  public TestKubernetesOptimizerContainer() throws IOException {
+    // generating configuration files
+    containerProperties.put(OptimizerProperties.AMS_HOME, "/home/ams");
+    containerProperties.put(OptimizerProperties.AMS_OPTIMIZER_URI, 
"thrift://127.0.0.1:1261");
+    URL resource = getClass().getClassLoader().getResource("config.yaml");
+
+    JsonNode yamlConfig =
+        JacksonUtil.fromObjects(
+            new 
Yaml().loadAs(Files.newInputStream(Paths.get(resource.getPath())), Map.class));
+    JsonNode containers = yamlConfig.get(AmoroManagementConf.CONTAINER_LIST);
+    for (JsonNode container : containers) {
+      if (container.get("name").asText().equals("KubernetesContainer")) {
+        ObjectMapper mapper = new ObjectMapper();
+        
containerProperties.putAll(mapper.convertValue(container.get("properties"), 
Map.class));
+      }
+    }
+  }
+
+  private static String checkAndGetProperty(Map<String, String> properties, 
String key) {
+    Preconditions.checkState(
+        properties != null && properties.containsKey(key), "Cannot find %s in 
properties", key);
+    return properties.get(key);
+  }
+
+  @Test
+  public void testBuildPodTemplateConfig() {
+    Map<String, String> groupProperties = Maps.newHashMap();
+    groupProperties.putAll(this.containerProperties);
+
+    // before parameter merging
+    PodTemplate podTemplate =
+        kubernetesOptimizerContainer.initPodTemplateFromLocal(groupProperties);
+
+    // after parameter merging
+
+    // generating frontend
+    ResourceType resourceType = ResourceType.OPTIMIZER;
+    Map<String, String> properties = Maps.newHashMap();
+    properties.put("memory", "1024");
+    Resource resource =
+        new Resource.Builder("KubernetesContainer", "k8s", resourceType)
+            .setMemoryMb(0)
+            .setThreadCount(1)
+            .setProperties(properties)
+            .build();
+    groupProperties.putAll(resource.getProperties());
+
+    // generate pod start args
+    long memoryPerThread = Long.parseLong(checkAndGetProperty(groupProperties, 
MEMORY_PROPERTY));
+    long memory = memoryPerThread * resource.getThreadCount();
+    String startUpArgs =
+        String.format(
+            "/entrypoint.sh optimizer %s %s",
+            memory, 
kubernetesOptimizerContainer.buildOptimizerStartupArgsString(resource));
+    String image = checkAndGetProperty(groupProperties, IMAGE);
+    String pullPolicy = checkAndGetProperty(groupProperties, PULL_POLICY);
+    String pullSecrets = groupProperties.getOrDefault(PULL_SECRETS, "");
+    String cpuLimitFactorString = 
groupProperties.getOrDefault(CPU_FACTOR_PROPERTY, "1.0");
+    double cpuLimitFactor = Double.parseDouble(cpuLimitFactorString);
+    int cpuLimit = (int) (Math.ceil(cpuLimitFactor * 
resource.getThreadCount()));
+
+    List<LocalObjectReference> imagePullSecretsList =
+        Arrays.stream(pullSecrets.split(";"))
+            .map(secret -> new 
LocalObjectReferenceBuilder().withName(secret).build())
+            .collect(Collectors.toList());
+
+    String resourceId = resource.getResourceId();
+    String groupName = resource.getGroupName();
+
+    Deployment deployment =
+        kubernetesOptimizerContainer.initPodTemplateFromFrontEnd(
+            podTemplate,
+            image,
+            pullPolicy,
+            cpuLimit,
+            groupName,
+            resourceId,
+            startUpArgs,
+            memory,
+            imagePullSecretsList);
+
+    Assert.assertEquals("amoro-optimizer-" + resourceId, 
deployment.getMetadata().getName());
+    Assert.assertEquals(
+        "k8s",
+        
deployment.getSpec().getTemplate().getMetadata().getLabels().get("AmoroOptimizerGroup"));

Review Comment:
   Here they need to reflect their mutual priorities and need to be split into 
different methods for independent testing to cover each other's priorities.



-- 
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