minamijoyo/tfmigrate

Integration in CI/CD pipeline when there are also non-migration changes

Closed this issue · 3 comments

WVan commented

Hi, this looks like the tool I need, but I'm having some trouble integrating it into our CI/CD pipeline, perhaps you can help.

Current situation

Currently we have to do our migrations (state mv, import etc) manually, outside of the CI/CD pipeline. But aside from the migrations it works like this:

  • Changes in terraform code are made on a separate branch.
  • A merge/pull request is created for the branch.
  • CI/CD pipeline does a terraform plan.
  • Reviewer checks the terraform code and the output of the plan.
  • Branch is merged into the main branch.
  • CI/CD pipeline does another terraform plan (to ensure no changes were done on the main branch in the mean time).
  • Reviewer checks the plan again.
  • Reviewer starts manual job in the CI/CD pipeline that runs terraform apply with the previously created plan.

Desired situation

I would love to use tfmigrate in history mode to do all our migrations for us at the same time as the terraform code for the migrations is actually merged and applied by the CI/CD pipeline. So I came up with this:

  • Changes in terraform code are made on a separate branch.
  • A merge/pull request is created for the branch.
  • CI/CD pipeline does a tfmigrate plan.
  • Reviewer checks the terraform code and the output of the plan.
  • Branch is merged into the main branch.
  • CI/CD pipeline does tfmigrate apply to apply the migrations that were merged (together with the terraform code causing the migrations)
  • CI/CD pipeline does another terraform plan (to ensure no changes were done on the main branch in the mean time).
  • Reviewer checks the plan again.
  • Reviewer starts manual job in the CI/CD pipeline that runs terraform apply with the previously created plan.

Difficulties

  • Our merge/pull requests will contain more than just migration code. For example there may be a mv/rename of a resource, but in the same merge request that resource' attributes are also changed. So tfmigrate plan results in a non-empty plan causing the CI/CD pipeline to fail.
  • And even if we would make separate merge/pull requests for migrations and 'normal' terraform changes, how would we combine both tfmigrate and 'normal' terraform plan/apply into the same pipeline without the tfmigrate part failing?
  • I tried using a wrapper script around the terraform command with TFMIGRATE_EXEC_PATH that always exits with a 0 exit code for the terraform plan command, but then tfmigrate doesn't seem to output the plan results to the console.

A potential solution might be to always have tfmigrate plan output the plan results and have an option for it to not fail when there are diffs. But perhaps I misunderstood and that is the wrong way of using the tool. Would you have any suggestions on how to properly integrate tfmigrate into our development pipeline while allowing 'normal' terraform changes besides the migrations?

Hi @WVan, Thank you for sharing your use-case!

It looks like a problem similar to #36. It had been implemented in #37, but it was recently deprecated in #63 due to a change in Terraform 1.1. At time of this writing with the latest tfmigrate v0.3.0 + Terraform v1.1.0, there is no perfect single solution due to some technical constraints.

Knowing that not all use cases can be covered, but the following might be help:

  • For renaming a resource address in a single tfstate, use a new moved block introduced in Terraform 1.1. See https://www.hashicorp.com/blog/terraform-1-1-improves-refactoring-and-the-cloud-cli-experience
  • For moving a resource accross two tfstates, use a multi_state migration in tfmigrate and not to include other normal configuration changes in a single pull request.
  • For importing or removing a resource in a single tfstate, use a state migration in tfmigrate with setting a force attribute to true, which allows you to apply migration even if it contains some plan changes, finally run a normal terraform apply to converge changes.

A native plannable import feature has been proposed in the upstream, but not implemented yet. hashicorp/terraform#26364

After thinking about how to implement a pipeline, you may simplify them into the 3rd case because your pipeline already has a step for an approval before terraform apply, which allows you to review changes ignored by tfmigrate apply with the force attribute.

I'm going to close this because there has been no activity on this recently. Please feel free to reopen this if you have any questions or suggestions. Thanks!