Abyss-lord commented on code in PR #10296: URL: https://github.com/apache/gravitino/pull/10296#discussion_r3026267024
########## clients/cli/src/test/java/org/apache/gravitino/cli/commands/TestListModelVersionProperties.java: ########## Review Comment: I think we should move all Model-related command tests to `clients/cli/src/test/java/org/apache/gravitino/cli/TestModelCommands.java` ########## clients/cli/src/test/java/org/apache/gravitino/cli/commands/TestListModelVersionProperties.java: ########## @@ -0,0 +1,168 @@ +/* + * 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.gravitino.cli.commands; + +import java.util.HashMap; +import java.util.Map; +import org.apache.commons.cli.CommandLine; +import org.apache.gravitino.Catalog; +import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; +import org.apache.gravitino.cli.Main; +import org.apache.gravitino.client.GravitinoClient; +import org.apache.gravitino.model.ModelCatalog; +import org.apache.gravitino.model.ModelVersion; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +class TestListModelVersionProperties { + + @BeforeEach + void setUp() { + Main.useExit = false; + } + + @AfterEach + void tearDown() { + Main.useExit = true; + } + + @Test + void handleByVersionPrintsProperties() throws Exception { + CommandLine mockCmdLine = Mockito.mock(CommandLine.class); + CommandContext context = new CommandContext(mockCmdLine); + + ListModelVersionProperties command = + Mockito.spy( + new ListModelVersionProperties( + context, "metalake1", "catalog1", "schema1", "model1", 1, null)); + + GravitinoClient mockClient = Mockito.mock(GravitinoClient.class); + Catalog mockCatalog = Mockito.mock(Catalog.class); + ModelCatalog mockModelCatalog = Mockito.mock(ModelCatalog.class); + ModelVersion mockModelVersion = Mockito.mock(ModelVersion.class); + + Map<String, String> properties = new HashMap<>(); + properties.put("vp1", "vval1"); + properties.put("vp2", "vval2"); + + Mockito.doReturn(mockClient).when(command).buildClient("metalake1"); + Mockito.when(mockClient.loadCatalog("catalog1")).thenReturn(mockCatalog); + Mockito.when(mockCatalog.asModelCatalog()).thenReturn(mockModelCatalog); + Mockito.when(mockModelCatalog.getModelVersion(Mockito.any(NameIdentifier.class), Mockito.eq(1))) + .thenReturn(mockModelVersion); + Mockito.when(mockModelVersion.properties()).thenReturn(properties); + + command.handle(); + + Mockito.verify(mockModelCatalog).getModelVersion(NameIdentifier.of("schema1", "model1"), 1); + Mockito.verify(command).printProperties(properties); + } + + @Test + void handleByAliasPrintsProperties() throws Exception { + CommandLine mockCmdLine = Mockito.mock(CommandLine.class); + CommandContext context = new CommandContext(mockCmdLine); + + ListModelVersionProperties command = + Mockito.spy( + new ListModelVersionProperties( + context, "metalake1", "catalog1", "schema1", "model1", null, "v1")); + + GravitinoClient mockClient = Mockito.mock(GravitinoClient.class); + Catalog mockCatalog = Mockito.mock(Catalog.class); + ModelCatalog mockModelCatalog = Mockito.mock(ModelCatalog.class); + ModelVersion mockModelVersion = Mockito.mock(ModelVersion.class); + + Map<String, String> properties = new HashMap<>(); + properties.put("vp1", "vval1"); + + Mockito.doReturn(mockClient).when(command).buildClient("metalake1"); + Mockito.when(mockClient.loadCatalog("catalog1")).thenReturn(mockCatalog); + Mockito.when(mockCatalog.asModelCatalog()).thenReturn(mockModelCatalog); + Mockito.when( + mockModelCatalog.getModelVersion(Mockito.any(NameIdentifier.class), Mockito.eq("v1"))) + .thenReturn(mockModelVersion); + Mockito.when(mockModelVersion.properties()).thenReturn(properties); + + command.handle(); + + Mockito.verify(mockModelCatalog).getModelVersion(NameIdentifier.of("schema1", "model1"), "v1"); + Mockito.verify(command).printProperties(properties); + } + + @Test + void handleWithBothNullVersionAndAliasShouldExitWithError() { + CommandLine mockCmdLine = Mockito.mock(CommandLine.class); + CommandContext context = new CommandContext(mockCmdLine); + + ListModelVersionProperties command = + new ListModelVersionProperties( + context, "metalake1", "catalog1", "schema1", "model1", null, null); + + RuntimeException ex = Assertions.assertThrows(RuntimeException.class, command::handle); + Assertions.assertTrue(ex.getMessage().contains("Exit with code")); + } Review Comment: I don't think it's possible for both `alias` and `version` in `ListModelVersionProperties` to be null at the same time, so there's no need to test for this scenario. ########## clients/cli/src/test/java/org/apache/gravitino/cli/commands/TestListModelProperties.java: ########## Review Comment: I think we should move all Model-related command tests to `clients/cli/src/test/java/org/apache/gravitino/cli/TestModelCommands.java` ########## clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListModelVersionProperties.java: ########## @@ -0,0 +1,122 @@ +/* + * 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.gravitino.cli.commands; + +import java.util.Map; +import javax.annotation.Nullable; +import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; +import org.apache.gravitino.cli.ErrorMessages; +import org.apache.gravitino.client.GravitinoClient; +import org.apache.gravitino.exceptions.NoSuchCatalogException; +import org.apache.gravitino.exceptions.NoSuchMetalakeException; +import org.apache.gravitino.exceptions.NoSuchModelException; +import org.apache.gravitino.exceptions.NoSuchModelVersionException; +import org.apache.gravitino.exceptions.NoSuchSchemaException; +import org.apache.gravitino.model.ModelCatalog; +import org.apache.gravitino.model.ModelVersion; + +/** List the properties of a model version. */ +public class ListModelVersionProperties extends ListProperties { + + /** The name of the metalake. */ + protected final String metalake; + /** The name of the catalog. */ + protected final String catalog; + /** The name of the schema. */ + protected final String schema; + /** The name of the model. */ + protected final String model; + /** The version number of the model version. */ + @Nullable protected final Integer version; + /** The alias of the model version. */ + @Nullable protected final String alias; + + /** + * List the properties of a model version. + * + * @param context The command context. + * @param metalake The name of the metalake. + * @param catalog The name of the catalog. + * @param schema The name of the schema. + * @param model The name of the model. + * @param version The version number of the model version. + * @param alias The alias of the model version. + */ + public ListModelVersionProperties( + CommandContext context, + String metalake, + String catalog, + String schema, + String model, + @Nullable Integer version, + @Nullable String alias) { + super(context); + this.metalake = metalake; + this.catalog = catalog; + this.schema = schema; + this.model = model; + this.version = version; + this.alias = alias; + } + + /** List the properties of a model version. */ + @Override + public void handle() { + ModelVersion gModelVersion = null; + try { + NameIdentifier name = NameIdentifier.of(schema, model); + GravitinoClient client = buildClient(metalake); + ModelCatalog modelCatalog = client.loadCatalog(catalog).asModelCatalog(); + if (version != null) { + gModelVersion = modelCatalog.getModelVersion(name, version); + } else { + gModelVersion = modelCatalog.getModelVersion(name, alias); + } + } catch (NoSuchMetalakeException err) { + exitWithError(ErrorMessages.UNKNOWN_METALAKE); + } catch (NoSuchCatalogException err) { + exitWithError(ErrorMessages.UNKNOWN_CATALOG); + } catch (NoSuchSchemaException err) { + exitWithError(ErrorMessages.UNKNOWN_SCHEMA); + } catch (NoSuchModelException err) { + exitWithError(ErrorMessages.UNKNOWN_MODEL); + } catch (NoSuchModelVersionException err) { + exitWithError(ErrorMessages.UNKNOWN_MODEL_VERSION); + } catch (Exception exp) { + exitWithError(exp.getMessage()); + } + + Map<String, String> properties = gModelVersion.properties(); + printProperties(properties); + } + + /** {@inheritDoc} */ + @Override + public Command validate() { + if (alias != null && version != null) { + exitWithError("Cannot specify both alias and version"); + } + if (alias == null && version == null) { + exitWithError("Either alias or version must be specified"); + } + return this; + } Review Comment: Please define the error message in `ErrorMessages` ########## clients/cli/src/main/java/org/apache/gravitino/cli/ModelCommandHandler.java: ########## @@ -310,6 +314,23 @@ private void handleRemoveCommand() { } } + /** Handles the "PROPERTIES" command. */ + private void handlePropertiesCommand() { + if (line.hasOption(GravitinoOptions.ALIAS) || line.hasOption(GravitinoOptions.VERSION)) { + Integer version = getVersionFromLine(line); + String alias = getAliasFromLine(line); + gravitinoCommandLine + .newListModelVersionProperties(context, metalake, catalog, schema, model, version, alias) + .validate() + .handle(); + } else { + gravitinoCommandLine + .newListModelProperties(context, metalake, catalog, schema, model) + .validate() + .handle(); + } Review Comment: plz update `clients/cli/src/main/resources/model_help.txt` ########## clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListModelVersionProperties.java: ########## @@ -0,0 +1,122 @@ +/* + * 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.gravitino.cli.commands; + +import java.util.Map; +import javax.annotation.Nullable; +import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; +import org.apache.gravitino.cli.ErrorMessages; +import org.apache.gravitino.client.GravitinoClient; +import org.apache.gravitino.exceptions.NoSuchCatalogException; +import org.apache.gravitino.exceptions.NoSuchMetalakeException; +import org.apache.gravitino.exceptions.NoSuchModelException; +import org.apache.gravitino.exceptions.NoSuchModelVersionException; +import org.apache.gravitino.exceptions.NoSuchSchemaException; +import org.apache.gravitino.model.ModelCatalog; +import org.apache.gravitino.model.ModelVersion; + +/** List the properties of a model version. */ +public class ListModelVersionProperties extends ListProperties { + + /** The name of the metalake. */ + protected final String metalake; + /** The name of the catalog. */ + protected final String catalog; + /** The name of the schema. */ + protected final String schema; + /** The name of the model. */ + protected final String model; + /** The version number of the model version. */ + @Nullable protected final Integer version; + /** The alias of the model version. */ + @Nullable protected final String alias; + + /** + * List the properties of a model version. + * + * @param context The command context. + * @param metalake The name of the metalake. + * @param catalog The name of the catalog. + * @param schema The name of the schema. + * @param model The name of the model. + * @param version The version number of the model version. + * @param alias The alias of the model version. + */ + public ListModelVersionProperties( + CommandContext context, + String metalake, + String catalog, + String schema, + String model, + @Nullable Integer version, + @Nullable String alias) { + super(context); + this.metalake = metalake; + this.catalog = catalog; + this.schema = schema; + this.model = model; + this.version = version; + this.alias = alias; + } + + /** List the properties of a model version. */ + @Override + public void handle() { + ModelVersion gModelVersion = null; + try { + NameIdentifier name = NameIdentifier.of(schema, model); + GravitinoClient client = buildClient(metalake); + ModelCatalog modelCatalog = client.loadCatalog(catalog).asModelCatalog(); + if (version != null) { + gModelVersion = modelCatalog.getModelVersion(name, version); + } else { + gModelVersion = modelCatalog.getModelVersion(name, alias); + } + } catch (NoSuchMetalakeException err) { + exitWithError(ErrorMessages.UNKNOWN_METALAKE); + } catch (NoSuchCatalogException err) { + exitWithError(ErrorMessages.UNKNOWN_CATALOG); + } catch (NoSuchSchemaException err) { + exitWithError(ErrorMessages.UNKNOWN_SCHEMA); + } catch (NoSuchModelException err) { + exitWithError(ErrorMessages.UNKNOWN_MODEL); + } catch (NoSuchModelVersionException err) { + exitWithError(ErrorMessages.UNKNOWN_MODEL_VERSION); + } catch (Exception exp) { + exitWithError(exp.getMessage()); + } + + Map<String, String> properties = gModelVersion.properties(); + printProperties(properties); + } + + /** {@inheritDoc} */ + @Override + public Command validate() { + if (alias != null && version != null) { + exitWithError("Cannot specify both alias and version"); + } + if (alias == null && version == null) { + exitWithError("Either alias or version must be specified"); + } Review Comment: I don't think this needs to be checked; the `ModelCommandHandler` ensures that both cannot be null at the same time during dispatch. -- 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]
