Skip to content

feat: cluster upgrade recommendation#50

Open
satyampsoni wants to merge 1 commit into
devtron-labs:mainfrom
satyampsoni:migration-feature
Open

feat: cluster upgrade recommendation#50
satyampsoni wants to merge 1 commit into
devtron-labs:mainfrom
satyampsoni:migration-feature

Conversation

@satyampsoni

Copy link
Copy Markdown

Add Migration File Generation Feature

Description

This PR adds a new feature to generate migration files when Kubernetes API versions change between different Kubernetes versions. The feature helps users automatically generate updated manifests with the correct API versions while preserving all other configurations.

Changes

  • Added new command-line flags:
    • --generate-migration-files: Enable migration file generation
    • --migration-output-dir: Specify output directory for migration files (default: "migrations")
  • Added Resource field to ValidationResult struct to store original resource data
  • Implemented MigrationFileGenerator to handle migration file creation
  • Modified validation process to preserve original resource data
  • Added migration file generation logic to both file and cluster processing

How it Works

  1. When the --generate-migration-files flag is used, the tool:

    • Validates resources against both source and target Kubernetes versions
    • Identifies API version changes (e.g., extensions/v1beta1apps/v1)
    • Generates migration files with updated API versions
    • Preserves all other resource configurations
  2. Migration files are generated with names following the format:

    {namespace}-{name}-{kind}.yaml
    
  3. Each migration file contains:

    • Updated API version
    • Original resource configuration
    • Properly formatted metadata

Example Usage

./kubedd test-yamls/old-deployment.yaml \
  --generate-migration-files \
  --migration-output-dir ./migration-files \
  --source-kubernetes-version 1.30 \
  --target-kubernetes-version 1.31 \
  --source-schema-location ./schemas/1.30.json \
  --target-schema-location ./schemas/1.31.json

Testing

  • Tested with various resource types (Deployments, Ingress, Roles)
  • Confirmed preservation of resource configurations
  • Validated file naming and directory creation

Benefits

  • Automates the process of updating API versions
  • Reduces manual work in Kubernetes version upgrades
  • Preserves all resource configurations
  • Provides clear migration path for users

Related Issues

#13

@satyampsoni satyampsoni changed the title feat:cluster upgrade recommendation feat: cluster upgrade recommendation Apr 11, 2025
Comment thread main.go
if generateMigrationFiles {
generator := pkg.NewMigrationFileGenerator(migrationOutputDir, noColor)
if err := generator.GenerateMigrationFiles(aggResults); err != nil {
log.Fatalf("Failed to generate migration files: %v", err)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

don't use log.fatal here ,let's just print the error here using log2.Error(err) and return success as false , and let the callee handle the os.Exit part.

Comment thread main.go
Comment on lines +301 to +302
RootCmd.Flags().BoolVar(&generateMigrationFiles, "generate-migration-files", false, "Generate migration files for API version updates")
RootCmd.Flags().StringVar(&migrationOutputDir, "migration-output-dir", "migrations", "Directory to store generated migration files")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

are we expecting user to give both these flags to generate manifest files ? can't we just take single flag i.e the path they want to store the generated manifest and check from code that if length of this flag is >0 then user want to generate the manifest file
This'll ensure it's more user friendly as they would need to give single flag to generate manifest.

Also let's change the name of migration-output-dir to --upgraded-manifests-dir , this single flag would be necessary as this will clearly express the intentions of the flag

Comment thread main.go
success = false
}

if generateMigrationFiles {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

one flag changes are done , check on len() instead of this flag

Comment thread pkg/Output.go
Put(r ValidationResult) error
Flush() error
GetSummaryValidationResultBulk() []SummaryValidationResult
GenerateMigrationFiles(results []ValidationResult, outputDir string) error

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Rename this func. to WriteUpgradedClusterManifests , this clearly shows func's intentions , GenerateMigrationFiles this is vague .

Comment thread pkg/Output.go
Comment on lines +585 to +588
type MigrationFileGenerator struct {
outputDir string
noColor bool
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

change name to ManifestExporter
this can act as generic manifest generator, say for example if we want to generate manifest for old cluster version's data then I can use this struct and it's methods implemented on it . rn it's only for migrated files

Comment thread main.go
Comment on lines +206 to +207
generator := pkg.NewMigrationFileGenerator(migrationOutputDir, noColor)
if err := generator.GenerateMigrationFiles(results); err != nil {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You should use outputManager.GenerateMigrationFiles (aftger renaming this func use renamed func name ) since you have already bound this func to OutputManager

Comment thread pkg/Types.go
Deprecated bool
LatestAPIVersion string
IsVersionSupported int
Resource map[string]interface{} `json:"resource,omitempty"`

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why is json tag necessary here ?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Also what will this key store ?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

make the different struct ?

Comment thread pkg/Output.go
for _, result := range results {
// Generate migration file for each resource, even if it has errors
if err := m.generateMigrationFile(result); err != nil {
return fmt.Errorf("failed to generate migration file for %s/%s: %v",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this is not optimal, this error printing in for loop will fill the whole terminal with errors which will also be unreadable , instead of this use struct to store error resp. for each errored result (gvk) and just continue generating manifest for other resources , for errored manifest just iterate over them and maybe generate another file with errored manifest output

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

let's disc this on monday I've few more pointers regarding this

Comment thread pkg/Output.go
Comment on lines +616 to +618
result.ResourceNamespace,
result.ResourceName,
strings.ToLower(result.Kind))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

strings.ToLower is applied for kind , can we apply it for ResourceNamespace and ResourceName as well as general convention

Comment thread pkg/Output.go
}

func (m *MigrationFileGenerator) GenerateMigrationFiles(results []ValidationResult) error {
if err := os.MkdirAll(m.outputDir, 0755); err != nil {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

let's lower the permission level for this file , generally 755 permiossion is given to files or dirs which contains executables , since this only contains files to be read, lets make this 644

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants