Skip to content

Commit

Permalink
#15: Adding Poetry Python package migration in foundation-upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
jacksondelametter committed May 3, 2024
1 parent ab71ced commit 0625dc2
Show file tree
Hide file tree
Showing 11 changed files with 435 additions and 2 deletions.
2 changes: 1 addition & 1 deletion DRAFT_RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ To reduce burden of upgrading aiSSEMBLE, the Baton project is used to automate t
| upgrade-v2-chart-files-aissemble-version-migration | Updates the helm chart dependencies within your project's deployment resources (<YOUR_PROJECT>-deploy/src/main/resources/apps/) to use the latest version of the aiSSEMBLE |
| upgrade-v1-chart-files-aissemble-version-migration | Updates the docker image tags within your project's deployment resources (<YOUR_PROJECT>-deploy/src/main/resources/apps/) to use the latest version of the aiSSEMBLE |
| upgrade-mlflow-v2-external-s3-migration | Update the mlflow V2 deployment (if present) in your project to utilize Localstack for local development and SealedSecrets for remote deployments |
| <pyproject-migration> | Will need to migrate pyproject.toml files to reflect newly named Python modules |
| upgrade-foundation-extension-python-package-migration | Updates the pyproject.toml files within your projects pipelines folder (<YOUR_PROJECT>-pipelines) to use the updated aiSSEMBLE foundation and extension Python packages with the latest naming convention | |

To deactivate any of these migrations, add the following configuration to the `baton-maven-plugin` within your root `pom.xml`:

Expand Down
2 changes: 1 addition & 1 deletion build-parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@
<operatorAndVersion>${version.aissemble}</operatorAndVersion>
</packageDefinition>
<packageDefinition>
<packageName>foundation-model-lineage</packageName>
<packageName>aissemble-foundation-model-lineage</packageName>
<operatorAndVersion>${version.aissemble}</operatorAndVersion>
</packageDefinition>
<packageDefinition>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.boozallen.aissemble.upgrade.migration;

/*-
* #%L
* aiSSEMBLE::Foundation::Upgrade
* %%
* Copyright (C) 2021 Booz Allen
* %%
* This software package is licensed under the Booz Allen Public License. All Rights Reserved.
* #L%
*/

import java.io.File;
import java.io.IOException;
import java.util.Optional;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.boozallen.aissemble.upgrade.util.FileUtils;
import com.boozallen.aissemble.upgrade.util.PythonPackageMigration;
import com.electronwill.nightconfig.core.Config;
import com.electronwill.nightconfig.core.file.FileConfig;

/**
*
* Baton migration used to migrate aiSSEMBLE python packages to the new naming convention
*/
public abstract class AbstractPoetryMigration extends AbstractAissembleMigration {

private static final Logger logger = LoggerFactory.getLogger(AbstractPoetryMigration.class);
public static final String DEPENDENCIES_KEY = "tool.poetry.dependencies";

@Override
protected boolean shouldExecuteOnFile(File file) {
boolean shouldExecute = false;
FileConfig poetryConfig = FileConfig.of(file);
poetryConfig.load();
Optional<Config> dependenciesOpt = poetryConfig.getOptional(DEPENDENCIES_KEY);
if(dependenciesOpt.isPresent()) {
Config dependencies = dependenciesOpt.get();
shouldExecute = hasOldPackages(dependencies);
}
else {
logger.warn("Could not get dependencies for file {}", file.getAbsolutePath());
}
return shouldExecute;
}

private boolean hasOldPackages(Config currentPackages) {
boolean hasOldPackages = false;
for(PythonPackageMigration packageMigration : getPythonPackageMigrations()) {
if(currentPackages.contains(packageMigration.getOldName())) {
hasOldPackages = true;
break;
}
}
return hasOldPackages;
}

@Override
protected boolean performMigration(File file) {
boolean performedSuccessfully = false;
FileConfig pyproject = FileConfig.of(file);
pyproject.load();
Config dependencies = pyproject.get(DEPENDENCIES_KEY);
try {
performedSuccessfully = migrateOldPythonPackages(dependencies, file);
} catch (IOException e) {
logger.error(e.getMessage());
}
return performedSuccessfully;
}

private boolean migrateOldPythonPackages(Config config, File pyproject) throws IOException {
boolean success = false;
for(PythonPackageMigration packageMigration : getPythonPackageMigrations()) {
String oldPackageName = packageMigration.getOldName();
if(config.getOptional(oldPackageName).isPresent()) {
// Old package is preset in pyproject.toml
String regex = String.format("%s = \".+\"", packageMigration.getOldName());
String replacement = String.format("%s = \"%s\"", packageMigration.getNewName(), packageMigration.getNewVersion());
FileUtils.replaceInFile(pyproject, regex, replacement);
logger.info("Replacing Python package {} -> {} = \"{}\"",
packageMigration.getOldName(), packageMigration.getNewName(), packageMigration.getNewVersion());
success = true;
}
}
return success;
}

public abstract Set<PythonPackageMigration> getPythonPackageMigrations();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.boozallen.aissemble.upgrade.migration.v1_7_0;

import java.util.HashSet;

/*-
* #%L
* aiSSEMBLE::Foundation::Upgrade
* %%
* Copyright (C) 2021 Booz Allen
* %%
* This software package is licensed under the Booz Allen Public License. All Rights Reserved.
* #L%
*/

import java.util.Set;

import com.boozallen.aissemble.upgrade.migration.AbstractPoetryMigration;
import com.boozallen.aissemble.upgrade.util.PythonPackageMigration;

public class FoundationExtensionPythonPackageMigration extends AbstractPoetryMigration {

private static final Set<String> OLD_PYTHON_PACKAGES = Set.of(
"foundation-core-python",
"foundation-pdp-client-python",
"foundation-model-lineage",
"foundation-encryption-policy-python",
"extensions-encryption-vault-python",
"extensions-data-delivery-spark-py",
"foundation-data-lineage-python"
);
private static final String PACKAGE_PREFIX = "aissemble-";

@Override
public Set<PythonPackageMigration> getPythonPackageMigrations() {
Set<PythonPackageMigration> packageMigrations = new HashSet<>();
String aissembleVersion = getAissembleVersion().replaceAll("-SNAPSHOT", ".*");
for(String oldPackageName : OLD_PYTHON_PACKAGES) {
String newPackageName = String.format("%s%s", PACKAGE_PREFIX, oldPackageName);
packageMigrations.add(new PythonPackageMigration(oldPackageName, newPackageName, aissembleVersion));
}
return packageMigrations;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.boozallen.aissemble.upgrade.util;

/*-
* #%L
* aiSSEMBLE::Foundation::Upgrade
* %%
* Copyright (C) 2021 Booz Allen
* %%
* This software package is licensed under the Booz Allen Public License. All Rights Reserved.
* #L%
*/


public class PythonPackageMigration {

private final String oldName;
private final String newName;
private final String newVersion;

public PythonPackageMigration(String oldName, String newName, String newVersion) {
this.oldName = oldName;
this.newName = newName;
this.newVersion = newVersion;
}

public String getOldName() {
return this.oldName;
}

public String getNewName() {
return this.newName;
}

public String getNewVersion() {
return this.newVersion;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@
}
]
},
{
"name": "upgrade-foundation-extension-python-package-migration",
"implementation": "com.boozallen.aissemble.upgrade.migration.v1_7_0.FoundationExtensionPythonPackageMigration",
"fileSets": [
{
"includes": ["*-pipelines/**/pyproject.toml"]
}
]
},
{
"name": "upgrade-v1-chart-files-aissemble-version-migration",
"implementation": "com.boozallen.aissemble.upgrade.migration.HelmChartsV1Migration",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,25 @@
*/

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;

public class AbstractMigrationTest {
protected File testFile;
protected boolean shouldExecute;
protected boolean successful;

private static final String TEST_FILES_FOLDER = Paths.get("target", "test-classes", "test-files").toString();

protected static void addTestFile(String subPath) throws IOException {
File testFile = Paths.get(TEST_FILES_FOLDER, subPath).toFile();
if(testFile.exists()) {
throw new RuntimeException(String.format("Test file at %s already exists", subPath));
}
testFile.getParentFile().mkdirs();
testFile.createNewFile();
}

protected static File getTestFile(String subPath) {
File testFile = Paths.get("target", "test-classes", "test-files", subPath).toFile();
File dir = testFile.getParentFile();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.boozallen.aissemble.upgrade.migration;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import org.junit.AfterClass;
import org.junit.BeforeClass;

import com.boozallen.aissemble.upgrade.migration.extensions.PoetryMigrationTest;
import com.boozallen.aissemble.upgrade.util.PythonPackageMigration;
import com.electronwill.nightconfig.core.Config;
import com.electronwill.nightconfig.core.file.FileConfig;

import io.cucumber.java.Before;

/*-
* #%L
* aiSSEMBLE::Foundation::Upgrade
* %%
* Copyright (C) 2021 Booz Allen
* %%
* This software package is licensed under the Booz Allen Public License. All Rights Reserved.
* #L%
*/

import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import static com.boozallen.aissemble.upgrade.migration.utils.PoetryMigrationUtils.getOldPackages;
import static com.boozallen.aissemble.upgrade.migration.utils.PoetryMigrationUtils.createPyproject;
import static com.boozallen.aissemble.upgrade.migration.utils.PoetryMigrationUtils.getPartialOldPythonPackages;
import static com.boozallen.aissemble.upgrade.migration.utils.PoetryMigrationUtils.getNewPackages;
import static com.boozallen.aissemble.upgrade.migration.utils.PoetryMigrationUtils.verifyPoetryMigration;


public class PoetryMigrationSteps extends AbstractMigrationTest {

private static final String PYPROJECT_FILE = Paths.get("pyproject", "pyproject.toml").toString();
private static AbstractPoetryMigration migration;

@BeforeClass
public void createTestPyproject() throws IOException {
addTestFile(PYPROJECT_FILE);
}

@AfterClass
public void deletePyproject() {
getTestFile(PYPROJECT_FILE).delete();
}

@Before
public void setTestFile() {
testFile = getTestFile(PYPROJECT_FILE);
migration = new PoetryMigrationTest();
}

@Given("a pyproject.toml file with old aiSSEMBLE Python dependency naming conventions and versions")
public void a_pyproject_toml_file_with_all_old_ai_ssemble_python_dependencies() throws IOException {
createPyproject(getOldPackages(migration.getPythonPackageMigrations()), testFile);
}

@Given("a pyproject.toml file with old and new aiSSEMBLE Python dependency naming conventions and versions")
public void a_pyproject_toml_file_with_old_ai_ssemble_python_dependencies() throws IOException {
createPyproject(getPartialOldPythonPackages(migration.getPythonPackageMigrations()), testFile);
}

@Given("a pyproject.toml file with new aiSSEMBLE Python dependencies")
public void a_pyproject_toml_file_with_new_ai_ssemble_python_dependencies() {
createPyproject(getNewPackages(migration.getPythonPackageMigrations()), testFile);
}

@When("the pyproject.toml file migration is executed")
public void the_pyproject_toml_file_migration_is_executed() {
performMigration(migration);
}

@Then("the migration is skipped")
public void the_migration_is_skipped() {
assertFalse(shouldExecute);
}

@Then("the dependencies are updated to the newest naming convention and version")
public void the_dependencies_are_updated_to_the_newest_naming_convention() {
verifyPoetryMigration(migration.getPythonPackageMigrations(), testFile);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.boozallen.aissemble.upgrade.migration.extensions;

/*-
* #%L
* aiSSEMBLE::Foundation::Upgrade
* %%
* Copyright (C) 2021 Booz Allen
* %%
* This software package is licensed under the Booz Allen Public License. All Rights Reserved.
* #L%
*/

import java.util.Set;

import com.boozallen.aissemble.upgrade.migration.AbstractPoetryMigration;
import com.boozallen.aissemble.upgrade.util.PythonPackageMigration;

public class PoetryMigrationTest extends AbstractPoetryMigration {

private final static Set<PythonPackageMigration> MIGRATION_PYTHON_PACKAGES = Set.of(
new PythonPackageMigration("package_1", "new_package_1", "2.0.0"),
new PythonPackageMigration("package_2", "new_package_2", "2.0.0"),
new PythonPackageMigration("package_3", "new_package_3", "1.0.0")
);

@Override
public Set<PythonPackageMigration> getPythonPackageMigrations() {
return MIGRATION_PYTHON_PACKAGES;
}

}
Loading

0 comments on commit 0625dc2

Please sign in to comment.