Skip to content

Add Breaking Changes viewer to assessing-your-cluster-for-migration.md #9443

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Apr 8, 2025
61 changes: 61 additions & 0 deletions _data/migration-assistant/breaking-changes.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Breaking changes data for migration paths
#
# Data structure:
# breaking_changes: Array of breaking change objects with:
# - title: Display name of the breaking change
# - url: Link to documentation
# - introducedIn: Version where the breaking change was introduced
# - affects (optional): Object with minSource and maxTarget versions
# - minSource: Minimum source version affected
# - maxTarget: Maximum target version affected
# - comp: Array of components affected (e.g., ["dashboards"])
# - transformation (optional): Optional object with transformation information
# - title: Title of the transformation guide
# - url: Link to transformation guide
breaking_changes:
- title: "Amazon OpenSearch Service: Upgrade Guidance"
url: "https://docs.aws.amazon.com/opensearch-service/latest/developerguide/version-migration.html"
introducedIn: "OpenSearch 1.3"
comp: []
- title: "Amazon OpenSearch Service: Rename - Summary of changes"
url: "https://docs.aws.amazon.com/opensearch-service/latest/developerguide/rename.html"
introducedIn: "OpenSearch 1.3"
comp: []
- title: "OpenSearch 2.0: Remove mapping types parameter"
url: "/docs/latest/breaking-changes/#remove-mapping-types-parameter"
introducedIn: "OpenSearch 2.19"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about making these major version only? Otherwise we need to update this in many different positions on a version update.

Suggested change
introducedIn: "OpenSearch 2.19"
introducedIn: "OpenSearch 2.X"

Alternatively, introducedIn implies these changes should have appeared in the first version of OpenSearch 2.0, no?

I'd recommend being less specific for now and we can always build up if we want.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The versions here match the versions on supported migrations.
image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤷 It reads strange when looking in the non-table view. Not a blocker.

comp: []
transformation:
title: "Type Mapping Deprecation"
url: "/docs/latest/migration-assistant/migration-phases/planning-your-migration/handling-type-mapping-deprecation/"
- title: "OpenSearch Notifications Plugins"
url: "/breaking-changes/#add-opensearch-notifications-plugins"
introducedIn: "OpenSearch 2.19"
comp: []
- title: "OpenSearch 2.0: Client JDK 8 Support Dropped"
url: "/docs/latest/breaking-changes/#drop-support-for-jdk-8"
introducedIn: "OpenSearch 2.19"
comp: []
- title: "Removal of Types in Elasticsearch 7.x"
url: "https://www.elastic.co/guide/en/elasticsearch/reference/7.10/removal-of-types.html"
introducedIn: "Elasticsearch 7.10"
comp: []
transformation:
title: "Type Mapping Deprecation"
url: "/docs/latest/migration-assistant/migration-phases/planning-your-migration/handling-type-mapping-deprecation/"
- title: "Elasticsearch 6.0 - 6.6 Breaking Changes"
url: "https://www.elastic.co/guide/en/elasticsearch/reference/6.8/breaking-changes.html"
introducedIn: "Elasticsearch 6.8"
comp: []
- title: "Elasticsearch 7.0 - 7.10 Breaking Changes"
url: "https://www.elastic.co/guide/en/elasticsearch/reference/7.10/breaking-changes.html"
introducedIn: "Elasticsearch 7.10"
comp: []
- title: "Kibana 6 Breaking Changes"
url: "https://www.elastic.co/guide/en/kibana/6.8/breaking-changes.html"
introducedIn: "Elasticsearch 6.8"
comp: ["dashboards"]
- title: "Kibana 7 Breaking Changes"
url: "https://www.elastic.co/guide/en/kibana/7.10/breaking-changes.html"
introducedIn: "Elasticsearch 7.10"
comp: ["dashboards"]
24 changes: 24 additions & 0 deletions _data/migration-assistant/valid_migrations.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Migration paths for Migration Assistant
migration_paths:
- source: "Elasticsearch 5.6"
targets:
- "OpenSearch 1.3"
- "OpenSearch 2.19"
- source: "Elasticsearch 6.8"
targets:
- "OpenSearch 1.3"
- "OpenSearch 2.19"
- source: "Elasticsearch 7.10"
targets:
- "OpenSearch 1.3"
- "OpenSearch 2.19"
- source: "Elasticsearch 7.17"
targets:
- "OpenSearch 1.3"
- "OpenSearch 2.19"
- source: "OpenSearch 1.3"
targets:
- "OpenSearch 2.19"
- source: "OpenSearch 2.19"
targets:
- "OpenSearch 2.19"
55 changes: 55 additions & 0 deletions _migration-assistant/assets/css/breaking-changes-selector.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
.breaking-changes-selector {
background: #f5f7f7;
padding: 15px;
border-radius: 4px;
margin-bottom: 20px;
}

.breaking-changes-selector div {
margin: 10px 0;
}

.breaking-changes-selector label {
margin-right: 8px;
}

.breaking-changes-selector select {
margin-right: 15px;
padding: 4px;
}

.breaking-changes-selector input[type="checkbox"] {
margin-right: 4px;
}

#breaking-changes-results {
margin-top: 15px;
}

#breaking-changes-results ul {
margin-top: 10px;
}

.transformation-info {
margin-left: 20px;
padding: 5px 10px;
background-color: #e6f7ff;
border-left: 3px solid #1890ff;
margin-top: 5px;
margin-bottom: 5px;
font-size: 0.9em;
}

.component-checkbox {
display: inline-block;
margin-left: 20px;
}

.transformation-request {
margin-top: 15px;
padding: 10px;
background-color: #f0f0f0;
border-radius: 4px;
font-size: 0.9em;
font-style: italic;
}
195 changes: 195 additions & 0 deletions _migration-assistant/assets/js/breaking-changes-data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
/**
* Breaking changes data for migration paths
*
* Data structure:
* - VERSIONS: Array of version strings derived from valid_migrations.yml
* - VERSION_ORDER: Array of version strings in strict order (derived from VERSIONS)
* - breakingChanges: Array of breaking change objects with:
* - title: Display name of the breaking change
* - url: Link to documentation
* - introducedIn: Version where the breaking change was introduced
* - affects (optional): Object with minSource and maxTarget versions
* - minSource: Minimum source version affected
* - maxTarget: Maximum target version affected
* - comp: Array of components affected
* - transformation (optional): Optional object with transformation information
*/

// Variables to store version ordering
let VERSION_ORDER = [];

// Version utility functions that use the dynamically determined version order
export function getVersionIndex(version) {
const index = VERSION_ORDER.indexOf(version);
if (index === -1) throw new Error(`Unknown version: ${version}`);
return index;
}

export function isVersionBetween(target, min, max) {
const targetIdx = getVersionIndex(target);
const minIdx = getVersionIndex(min);
const maxIdx = getVersionIndex(max);
return targetIdx >= minIdx && targetIdx <= maxIdx;
}

// Helper function to determine version ordering based on migration paths
function determineVersionOrder(versions, migrationMap) {
// Start with a copy of all versions
const remainingVersions = [...versions];
const orderedVersions = [];

// First, find versions that are only sources (not targets)
// These are the oldest versions
const onlySources = versions.filter(v =>
!Object.values(migrationMap.targetToSources).flat().includes(v) &&
migrationMap.sourceToTargets[v]
);

// Add oldest versions first
onlySources.forEach(v => {
orderedVersions.push(v);
const index = remainingVersions.indexOf(v);
if (index !== -1) remainingVersions.splice(index, 1);
});

// Then add the rest based on migration paths
while (remainingVersions.length > 0) {
let added = false;

for (let i = 0; i < remainingVersions.length; i++) {
const version = remainingVersions[i];
const sources = migrationMap.targetToSources[version] || [];

// If all sources of this version are already in orderedVersions,
// we can add this version next
if (sources.every(s => orderedVersions.includes(s))) {
orderedVersions.push(version);
remainingVersions.splice(i, 1);
added = true;
break;
}
}

// If we couldn't add any version in this pass, there might be a cycle
// Just add the first remaining version to break the cycle
if (!added && remainingVersions.length > 0) {
orderedVersions.push(remainingVersions[0]);
remainingVersions.splice(0, 1);
}
}

return orderedVersions;
}

// Variables to store migration data
let VALID_MIGRATIONS = {};
let VERSIONS = [];
let MIGRATION_MAP = {
sourceToTargets: {},
targetToSources: {}
};

// Variables to store breaking changes data
let breakingChanges = [];

// Extract all unique versions for dropdowns
function extractUniqueVersions(migrationsMap) {
const versions = new Set();

// Add all sources
Object.keys(migrationsMap).forEach(source => {
versions.add(source);
});

// Add all targets
Object.values(migrationsMap).forEach(targets => {
targets.forEach(target => {
versions.add(target);
});
});

return Array.from(versions).sort();
}

// Function to generate the reverse mapping (target -> sources)
function generateReverseMigrationMap(forwardMap) {
const reverseMap = {};

Object.entries(forwardMap).forEach(([source, targets]) => {
targets.forEach(target => {
if (!reverseMap[target]) {
reverseMap[target] = [];
}
reverseMap[target].push(source);
});
});

return reverseMap;
}

// Function to initialize the migration data from the data attribute
function initializeMigrationData() {
const migrationDataElement = document.getElementById('migration-data');

if (migrationDataElement && migrationDataElement.dataset.migrationPaths) {
try {
// Parse the JSON data from the data attribute
const migrationPaths = JSON.parse(migrationDataElement.dataset.migrationPaths);

// Transform the data structure from YAML format to the expected JavaScript object format
VALID_MIGRATIONS = migrationPaths.reduce((acc, path) => {
acc[path.source] = path.targets;
return acc;
}, {});

// Now that we have the migration data, create the derived data structures
VERSIONS = extractUniqueVersions(VALID_MIGRATIONS);
MIGRATION_MAP = {
sourceToTargets: VALID_MIGRATIONS,
targetToSources: generateReverseMigrationMap(VALID_MIGRATIONS)
};

// Determine version ordering based on migration paths
VERSION_ORDER = determineVersionOrder(VERSIONS, MIGRATION_MAP);
console.log('Determined version order:', VERSION_ORDER);
} catch (error) {
console.error('Failed to parse migration data:', error);
// Fallback to empty object if parsing fails
VALID_MIGRATIONS = {};
VERSIONS = [];
MIGRATION_MAP = { sourceToTargets: {}, targetToSources: {} };
VERSION_ORDER = [];
}
} else {
console.error('Migration data element not found or empty');
}
}

// Function to initialize the breaking changes data from the data attribute
function initializeBreakingChangesData() {
const migrationDataElement = document.getElementById('migration-data');

if (!migrationDataElement || !migrationDataElement.dataset.breakingChanges) {
console.error('Breaking changes data not found in migration-data element. Make sure to add data-breaking-changes attribute.');
return;
}

try {
// Parse the JSON data from the data attribute
breakingChanges = JSON.parse(migrationDataElement.dataset.breakingChanges);
console.log('Loaded breaking changes data:', breakingChanges.length);
} catch (error) {
console.error('Failed to parse breaking changes data:', error);
// Fallback to empty array if parsing fails
breakingChanges = [];
}
}

// Initialize the data when the DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
initializeMigrationData();
initializeBreakingChangesData();
});

// Export the breaking changes array for use in other modules
export { breakingChanges };
Loading
Loading