blob: 5d0b5cac4023915931810a48bb82864799feab31 [file] [log] [blame]
/*
* 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.iotdb.confignode.persistence;
import org.apache.iotdb.commons.auth.AuthException;
import org.apache.iotdb.commons.auth.entity.PrivilegeType;
import org.apache.iotdb.commons.file.SystemFileFactory;
import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.commons.utils.FileUtils;
import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlan;
import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlanType;
import org.apache.iotdb.confignode.consensus.request.auth.AuthorPlan;
import org.apache.iotdb.confignode.consensus.request.write.database.DatabaseSchemaPlan;
import org.apache.iotdb.confignode.consensus.request.write.database.SetTTLPlan;
import org.apache.iotdb.confignode.consensus.request.write.template.CommitSetSchemaTemplatePlan;
import org.apache.iotdb.confignode.consensus.request.write.template.CreateSchemaTemplatePlan;
import org.apache.iotdb.confignode.consensus.request.write.template.PreSetSchemaTemplatePlan;
import org.apache.iotdb.confignode.persistence.schema.CNPhysicalPlanGenerator;
import org.apache.iotdb.confignode.persistence.schema.CNSnapshotFileType;
import org.apache.iotdb.confignode.persistence.schema.ClusterSchemaInfo;
import org.apache.iotdb.confignode.rpc.thrift.TDatabaseSchema;
import org.apache.iotdb.db.schemaengine.template.Template;
import org.apache.tsfile.enums.TSDataType;
import org.apache.tsfile.file.metadata.enums.CompressionType;
import org.apache.tsfile.file.metadata.enums.TSEncoding;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import static org.apache.iotdb.db.utils.constant.TestConstant.BASE_OUTPUT_PATH;
public class CNPhysicalPlanGeneratorTest {
private static AuthorInfo authorInfo;
private static ClusterSchemaInfo clusterSchemaInfo;
private static final File snapshotDir = new File(BASE_OUTPUT_PATH, "authorInfo-snapshot");
private static final String USER_SNAPSHOT_FILE_NAME = "system" + File.separator + "users";
private static final String ROLE_SNAPSHOT_FILE_NAME = "system" + File.separator + "roles";
private static final String SCHEMA_INFO_FILE_NAME = "cluster_schema.bin";
private static final String TEMPLATE_INFO_FILE_NAME = "template_info.bin";
private static void setupAuthorInfo() {
authorInfo = new AuthorInfo();
if (!snapshotDir.exists()) {
snapshotDir.mkdir();
}
}
private static void setupClusterSchemaInfo() throws IOException {
clusterSchemaInfo = new ClusterSchemaInfo();
if (!snapshotDir.exists()) {
snapshotDir.mkdir();
}
}
@After
public void cleanUpInfo() throws AuthException {
if (authorInfo != null) {
authorInfo.clear();
}
if (clusterSchemaInfo != null) {
clusterSchemaInfo.clear();
}
FileUtils.deleteFileOrDirectory(snapshotDir);
}
@Test
public void roleGeneratorTest() throws Exception {
final HashSet<Integer> answerSet = new HashSet<>();
String roleName = "test1";
setupAuthorInfo();
AuthorPlan plan = new AuthorPlan(ConfigPhysicalPlanType.CreateRole);
plan.setRoleName(roleName);
plan.setPermissions(new HashSet<>());
plan.setNodeNameList(new ArrayList<>());
answerSet.add(plan.hashCode());
// Step 1: create role - plan1
authorInfo.authorNonQuery(plan);
// Step 2: grant role path privileges - plan2
plan = new AuthorPlan(ConfigPhysicalPlanType.GrantRole);
plan.setRoleName(roleName);
plan.setUserName("");
plan.setNodeNameList(Collections.singletonList(new PartialPath("root.db.t1")));
final Set<Integer> pathPris = new HashSet<>();
pathPris.add(PrivilegeType.WRITE_DATA.ordinal());
pathPris.add(PrivilegeType.WRITE_SCHEMA.ordinal());
plan.setPermissions(pathPris);
authorInfo.authorNonQuery(plan);
// Answer set
plan.getPermissions().clear();
plan.getPermissions().add(PrivilegeType.WRITE_DATA.ordinal());
answerSet.add(plan.hashCode());
plan.getPermissions().clear();
plan.getPermissions().add(PrivilegeType.WRITE_SCHEMA.ordinal());
answerSet.add(plan.hashCode());
// Step 3: grant role sys privileges - plan3
plan = new AuthorPlan(ConfigPhysicalPlanType.GrantRole);
plan.setRoleName(roleName);
plan.setUserName("");
plan.setNodeNameList(Collections.emptyList());
final Set<Integer> sysPris = new HashSet<>();
sysPris.add(PrivilegeType.MANAGE_DATABASE.ordinal());
sysPris.add(PrivilegeType.MANAGE_ROLE.ordinal());
plan.setPermissions(sysPris);
plan.setGrantOpt(true);
authorInfo.authorNonQuery(plan);
// Answer set
plan.getPermissions().clear();
plan.getPermissions().add(PrivilegeType.MANAGE_ROLE.ordinal());
answerSet.add(plan.hashCode());
plan.getPermissions().clear();
plan.getPermissions().add(PrivilegeType.MANAGE_DATABASE.ordinal());
answerSet.add(plan.hashCode());
// PhysicalPlan generator will return five plans:
// 1. create role plan
// 2. grant path privileges plan * 2
// 3. grant system privileges plan * 2
Assert.assertTrue(authorInfo.processTakeSnapshot(snapshotDir));
final File roleProfile =
SystemFileFactory.INSTANCE.getFile(
snapshotDir
+ File.separator
+ ROLE_SNAPSHOT_FILE_NAME
+ File.separator
+ roleName
+ ".profile");
final CNPhysicalPlanGenerator planGenerator =
new CNPhysicalPlanGenerator(roleProfile.toPath(), CNSnapshotFileType.ROLE);
int count = 0;
for (ConfigPhysicalPlan authPlan : planGenerator) {
Assert.assertTrue(answerSet.contains(authPlan.hashCode()));
count++;
}
Assert.assertEquals(5, count);
}
@Test
public void userGeneratorTest() throws Exception {
final String userName = "test1";
final Set<Integer> answerSet = new HashSet<>();
setupAuthorInfo();
AuthorPlan plan = new AuthorPlan(ConfigPhysicalPlanType.CreateUser);
plan.setPassword("password");
plan.setUserName(userName);
plan.setPermissions(new HashSet<>());
plan.setNodeNameList(new ArrayList<>());
// Create user plan 1
authorInfo.authorNonQuery(plan);
answerSet.add(plan.hashCode());
plan = new AuthorPlan(ConfigPhysicalPlanType.CreateRole);
plan.setRoleName("role1");
plan.setPermissions(new HashSet<>());
plan.setNodeNameList(new ArrayList<>());
authorInfo.authorNonQuery(plan);
// Grant path privileges, plan 2 , plan 3
plan = new AuthorPlan(ConfigPhysicalPlanType.GrantUser);
plan.setUserName(userName);
plan.setRoleName("");
plan.setNodeNameList(Collections.singletonList(new PartialPath("root.db1.t2")));
final Set<Integer> priSet = new HashSet<>();
priSet.add(PrivilegeType.WRITE_SCHEMA.ordinal());
priSet.add(PrivilegeType.READ_DATA.ordinal());
plan.setPermissions(priSet);
plan.setGrantOpt(true);
authorInfo.authorNonQuery(plan);
plan.getPermissions().clear();
plan.getPermissions().add(PrivilegeType.WRITE_SCHEMA.ordinal());
answerSet.add(plan.hashCode());
plan.getPermissions().clear();
plan.getPermissions().add(PrivilegeType.READ_DATA.ordinal());
answerSet.add(plan.hashCode());
// Grant system privileges, plan 4
plan = new AuthorPlan(ConfigPhysicalPlanType.GrantUser);
plan.setUserName(userName);
plan.setRoleName("");
plan.setNodeNameList(Collections.emptyList());
plan.setPermissions(Collections.singleton(PrivilegeType.MANAGE_DATABASE.ordinal()));
plan.setGrantOpt(false);
authorInfo.authorNonQuery(plan);
answerSet.add(plan.hashCode());
// Grant role to user, plan 5
plan = new AuthorPlan(ConfigPhysicalPlanType.GrantRoleToUser);
plan.setRoleName("role1");
plan.setUserName("");
plan.setUserName(userName);
plan.setPermissions(new HashSet<>());
plan.setNodeNameList(new ArrayList<>());
authorInfo.authorNonQuery(plan);
answerSet.add(plan.hashCode());
Assert.assertTrue(authorInfo.processTakeSnapshot(snapshotDir));
final File userProfile =
SystemFileFactory.INSTANCE.getFile(
snapshotDir
+ File.separator
+ USER_SNAPSHOT_FILE_NAME
+ File.separator
+ userName
+ ".profile");
CNPhysicalPlanGenerator planGenerator =
new CNPhysicalPlanGenerator(userProfile.toPath(), CNSnapshotFileType.USER);
int count = 0;
// plan 1-4
for (ConfigPhysicalPlan authPlan : planGenerator) {
Assert.assertTrue(answerSet.contains(authPlan.hashCode()));
count++;
}
Assert.assertEquals(4, count);
final File roleListProfile =
SystemFileFactory.INSTANCE.getFile(
snapshotDir
+ File.separator
+ USER_SNAPSHOT_FILE_NAME
+ File.separator
+ userName
+ "_role.profile");
planGenerator =
new CNPhysicalPlanGenerator(roleListProfile.toPath(), CNSnapshotFileType.USER_ROLE);
count = 0;
// plan 5
for (ConfigPhysicalPlan authPlan : planGenerator) {
Assert.assertTrue(answerSet.contains(authPlan.hashCode()));
count++;
}
Assert.assertEquals(1, count);
}
@Test
public void databaseWithoutTemplateGeneratorTest() throws Exception {
setupClusterSchemaInfo();
final Set<Integer> answerSet = new HashSet<>();
final Set<String> storageGroupPathList = new TreeSet<>();
storageGroupPathList.add("root.sg");
storageGroupPathList.add("root.ln");
storageGroupPathList.add("root.a.sg");
storageGroupPathList.add("root.a.b.sg");
storageGroupPathList.add("root.a.a.a.b.sg");
int i = 0;
for (String path : storageGroupPathList) {
final TDatabaseSchema tDatabaseSchema = new TDatabaseSchema();
tDatabaseSchema.setName(path);
tDatabaseSchema.setTTL(i);
tDatabaseSchema.setDataReplicationFactor(i);
tDatabaseSchema.setSchemaReplicationFactor(i);
tDatabaseSchema.setTimePartitionInterval(i);
clusterSchemaInfo.createDatabase(
new DatabaseSchemaPlan(ConfigPhysicalPlanType.CreateDatabase, tDatabaseSchema));
final SetTTLPlan plan =
new SetTTLPlan(Arrays.asList(path.split("\\.")), tDatabaseSchema.getTTL());
answerSet.add(plan.hashCode());
TDatabaseSchema tDatabaseSchemaBak = new TDatabaseSchema(tDatabaseSchema);
tDatabaseSchemaBak.unsetTTL();
DatabaseSchemaPlan databaseSchemaPlan =
new DatabaseSchemaPlan(ConfigPhysicalPlanType.CreateDatabase, tDatabaseSchemaBak);
answerSet.add(databaseSchemaPlan.hashCode());
i++;
}
final boolean success = clusterSchemaInfo.processTakeSnapshot(snapshotDir);
Assert.assertTrue(success);
final File schemaInfo =
SystemFileFactory.INSTANCE.getFile(snapshotDir + File.separator + SCHEMA_INFO_FILE_NAME);
final File templateInfo =
SystemFileFactory.INSTANCE.getFile(snapshotDir + File.separator + TEMPLATE_INFO_FILE_NAME);
final CNPhysicalPlanGenerator planGenerator =
new CNPhysicalPlanGenerator(schemaInfo.toPath(), templateInfo.toPath());
int count = 0;
for (ConfigPhysicalPlan plan : planGenerator) {
if (plan.getType() == ConfigPhysicalPlanType.CreateDatabase) {
Assert.assertTrue(answerSet.contains(plan.hashCode()));
} else if (plan.getType() == ConfigPhysicalPlanType.SetTTL) {
final String[] database = ((SetTTLPlan) plan).getDatabasePathPattern();
final PartialPath databasePath = new PartialPath(database);
Assert.assertTrue(answerSet.contains(plan.hashCode()));
clusterSchemaInfo.setTTL((SetTTLPlan) plan);
}
count++;
}
planGenerator.checkException();
Assert.assertEquals(10, count);
}
@Test
public void templateGeneratorTest() throws Exception {
setupClusterSchemaInfo();
final Template t1 =
new Template(
"t1",
Arrays.asList("s1", "s2"),
Arrays.asList(TSDataType.INT32, TSDataType.BOOLEAN),
Arrays.asList(TSEncoding.GORILLA, TSEncoding.PLAIN),
Arrays.asList(CompressionType.GZIP, CompressionType.SNAPPY));
final Template t2 =
new Template(
"t2",
Arrays.asList("s1", "s2", "s3"),
Arrays.asList(TSDataType.INT32, TSDataType.BOOLEAN, TSDataType.TEXT),
Arrays.asList(TSEncoding.GORILLA, TSEncoding.PLAIN, TSEncoding.DIFF),
Arrays.asList(CompressionType.GZIP, CompressionType.SNAPPY, CompressionType.LZ4));
final Map<String, CreateSchemaTemplatePlan> answerPlan = new HashMap<>();
final CreateSchemaTemplatePlan plan1 = new CreateSchemaTemplatePlan(t1.serialize().array());
clusterSchemaInfo.createSchemaTemplate(plan1);
answerPlan.put(t1.getName(), plan1);
final CreateSchemaTemplatePlan plan2 = new CreateSchemaTemplatePlan(t2.serialize().array());
clusterSchemaInfo.createSchemaTemplate(plan2);
answerPlan.put(t2.getName(), plan2);
final boolean success = clusterSchemaInfo.processTakeSnapshot(snapshotDir);
Assert.assertTrue(success);
final File schemaInfo =
SystemFileFactory.INSTANCE.getFile(snapshotDir + File.separator + SCHEMA_INFO_FILE_NAME);
final File templateInfo =
SystemFileFactory.INSTANCE.getFile(snapshotDir + File.separator + TEMPLATE_INFO_FILE_NAME);
final CNPhysicalPlanGenerator planGenerator =
new CNPhysicalPlanGenerator(schemaInfo.toPath(), templateInfo.toPath());
int count = 0;
for (ConfigPhysicalPlan plan : planGenerator) {
final CreateSchemaTemplatePlan templatePlan = (CreateSchemaTemplatePlan) plan;
Assert.assertEquals(answerPlan.get(templatePlan.getTemplate().getName()), templatePlan);
count++;
}
Assert.assertEquals(2, count);
}
@Test
public void templateAndDatabaseCompletedTest() throws Exception {
setupClusterSchemaInfo();
final Set<Integer> answerSet = new HashSet<>();
final Set<String> storageGroupPathList = new TreeSet<>();
storageGroupPathList.add("root.sg");
storageGroupPathList.add("root.a.sg");
storageGroupPathList.add("root.a.b.sg");
storageGroupPathList.add("root.a.a.a.b.sg");
int i = 0;
for (String path : storageGroupPathList) {
final TDatabaseSchema tDatabaseSchema = new TDatabaseSchema();
tDatabaseSchema.setName(path);
tDatabaseSchema.setTTL(i);
tDatabaseSchema.setDataReplicationFactor(i);
tDatabaseSchema.setSchemaReplicationFactor(i);
tDatabaseSchema.setTimePartitionInterval(i);
clusterSchemaInfo.createDatabase(
new DatabaseSchemaPlan(ConfigPhysicalPlanType.CreateDatabase, tDatabaseSchema));
final SetTTLPlan plan =
new SetTTLPlan(Arrays.asList(path.split("\\.")), tDatabaseSchema.getTTL());
answerSet.add(plan.hashCode());
final TDatabaseSchema tDatabaseSchemaBak = new TDatabaseSchema(tDatabaseSchema);
tDatabaseSchemaBak.unsetTTL();
final DatabaseSchemaPlan databaseSchemaPlan =
new DatabaseSchemaPlan(ConfigPhysicalPlanType.CreateDatabase, tDatabaseSchemaBak);
answerSet.add(databaseSchemaPlan.hashCode());
i++;
}
final Template t1 =
new Template(
"t1",
Arrays.asList("s1", "s2"),
Arrays.asList(TSDataType.INT32, TSDataType.BOOLEAN),
Arrays.asList(TSEncoding.GORILLA, TSEncoding.PLAIN),
Arrays.asList(CompressionType.GZIP, CompressionType.SNAPPY));
final Template t2 =
new Template(
"t2",
Arrays.asList("s1", "s2", "s3"),
Arrays.asList(TSDataType.INT32, TSDataType.BOOLEAN, TSDataType.TEXT),
Arrays.asList(TSEncoding.GORILLA, TSEncoding.PLAIN, TSEncoding.DIFF),
Arrays.asList(CompressionType.GZIP, CompressionType.SNAPPY, CompressionType.LZ4));
final CreateSchemaTemplatePlan plan1 = new CreateSchemaTemplatePlan(t1.serialize().array());
clusterSchemaInfo.createSchemaTemplate(plan1);
answerSet.add(plan1.hashCode());
final CreateSchemaTemplatePlan plan2 = new CreateSchemaTemplatePlan(t2.serialize().array());
clusterSchemaInfo.createSchemaTemplate(plan2);
answerSet.add(plan2.hashCode());
final PreSetSchemaTemplatePlan preSetSchemaTemplatePlan1 =
new PreSetSchemaTemplatePlan("t1", "root.sg");
final PreSetSchemaTemplatePlan preSetSchemaTemplatePlan2 =
new PreSetSchemaTemplatePlan("t2", "root.a.sg.t1");
final CommitSetSchemaTemplatePlan setSchemaTemplatePlan1 =
new CommitSetSchemaTemplatePlan("t1", "root.sg");
final CommitSetSchemaTemplatePlan setSchemaTemplatePlan2 =
new CommitSetSchemaTemplatePlan("t2", "root.a.sg.t1");
clusterSchemaInfo.preSetSchemaTemplate(preSetSchemaTemplatePlan1);
clusterSchemaInfo.preSetSchemaTemplate(preSetSchemaTemplatePlan2);
clusterSchemaInfo.commitSetSchemaTemplate(setSchemaTemplatePlan1);
clusterSchemaInfo.commitSetSchemaTemplate(setSchemaTemplatePlan2);
answerSet.add(setSchemaTemplatePlan1.hashCode());
answerSet.add(setSchemaTemplatePlan1.hashCode());
final boolean success = clusterSchemaInfo.processTakeSnapshot(snapshotDir);
Assert.assertTrue(success);
final File schemaInfo =
SystemFileFactory.INSTANCE.getFile(snapshotDir + File.separator + SCHEMA_INFO_FILE_NAME);
final File templateInfo =
SystemFileFactory.INSTANCE.getFile(snapshotDir + File.separator + TEMPLATE_INFO_FILE_NAME);
final CNPhysicalPlanGenerator planGenerator =
new CNPhysicalPlanGenerator(schemaInfo.toPath(), templateInfo.toPath());
int count = 0;
for (ConfigPhysicalPlan plan : planGenerator) {
if (plan.getType() == ConfigPhysicalPlanType.CreateDatabase) {
Assert.assertTrue(answerSet.contains(plan.hashCode()));
} else if (plan.getType() == ConfigPhysicalPlanType.SetTTL) {
Assert.assertTrue(answerSet.contains(plan.hashCode()));
} else if (plan.getType() == ConfigPhysicalPlanType.CreateSchemaTemplate) {
Assert.assertTrue(answerSet.contains(plan.hashCode()));
} else if (plan.getType() == ConfigPhysicalPlanType.PreSetSchemaTemplate) {
Assert.assertTrue(answerSet.contains(plan.hashCode()));
} else if (plan.getType() == ConfigPhysicalPlanType.CommitSetSchemaTemplate) {
final CommitSetSchemaTemplatePlan commitSetSchemaTemplatePlan =
(CommitSetSchemaTemplatePlan) plan;
if (commitSetSchemaTemplatePlan.getName().equals("t1")) {
Assert.assertEquals(commitSetSchemaTemplatePlan, setSchemaTemplatePlan1);
} else {
Assert.assertEquals(commitSetSchemaTemplatePlan, setSchemaTemplatePlan1);
}
}
count++;
}
Assert.assertEquals(12, count);
}
}