Skip to content
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

Replace application already exists #329

Merged
merged 7 commits into from
Oct 26, 2023

Conversation

hmlanigan
Copy link
Member

@hmlanigan hmlanigan commented Oct 24, 2023

Description

CreateApplication in the juju package must be resilient to different already exists and not found errors. The method can be called when a new application resource is created, or when a RequiresReplace is triggered for the resource. In the case of RequiresReplace, DestroyApplication is called first. However we do not wait for the application removal to be done. Therefore we can get conflict errors when Creating an application with the same charm and or application name. Add retry functionality to account for this.

Side notes:

  • Fixed placement of ",", which was getting in the way of test runs.
  • Updated the integration resource example with needed info found during test.
  • The juju api isn't returning typed errors, add a method to convert errors to types for use here.

Fixes: #272

Type of change

  • Bug fix (non-breaking change which fixes an issue)

QA steps

Run terraform init && terraform plan && terraform apply with the following plan. Once it's active, update the plan by swapping the application names of "two" and "three", then run terraform plan && terraform apply.

terraform {
  required_providers {
    juju = {
      version = ">= 0.9.0"
      source  = "juju/juju"
    }
  }
}

provider "juju" {
}

resource "juju_model" "testmodel" {
  name = "replace"
}

resource "juju_application" "two" {
  model = juju_model.testmodel.name
  name = "juju-qa-test"
  units = 3
  charm {
    name = "juju-qa-test"
  }
}

resource "juju_application" "one" {
  model = juju_model.testmodel.name
  name = "ntp"
  charm {
    name = "ntp"
  }
  units = 0
}

resource "juju_integration" "juju-info" {
  model = juju_model.testmodel.name
  application {
    name = juju_application.one.name
    endpoint = "juju-info"
  }
  application {
    name = juju_application.two.name
    endpoint = "juju-info"
  }
  lifecycle {
    replace_triggered_by = [
      juju_application.one.name,
      juju_application.one.model,
      juju_application.one.constraints,
      juju_application.one.placement,
      juju_application.one.charm.name,
      juju_application.two.name,
      juju_application.two.model,
      juju_application.two.constraints,
      juju_application.two.placement,
      juju_application.two.charm.name,
    ]
  }
}

resource "juju_application" "three" {
  model = juju_model.testmodel.name
  name = "replace"
  charm {
    name = "ubuntu"
  }
}

Additional notes

JUJU-4529

@hmlanigan hmlanigan requested review from cderici and removed request for cderici October 24, 2023 19:01
@hmlanigan hmlanigan changed the title Replace application already exists WIP: Replace application already exists Oct 24, 2023
@hmlanigan hmlanigan force-pushed the replace-application-already-exists branch 3 times, most recently from f82a5d1 to e7c7666 Compare October 24, 2023 19:44
@hmlanigan hmlanigan requested a review from cderici October 25, 2023 14:36
@hmlanigan hmlanigan changed the title WIP: Replace application already exists Replace application already exists Oct 25, 2023
Copy link

@cderici cderici left a comment

Choose a reason for hiding this comment

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

Code looks good, previous errors I was hitting was because of mis-QA.

internal/provider/resource_application_test.go Outdated Show resolved Hide resolved
internal/provider/resource_application_test.go Outdated Show resolved Hide resolved
internal/provider/resource_application_test.go Outdated Show resolved Hide resolved
Copy link

@cderici cderici left a comment

Choose a reason for hiding this comment

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

LGTM 👍

Import of an application resource sometimes fails with placement
changing from "" to ",". The code should validate the size of the values
before doing the join to avoid this.
Errors are much easier to handle as typed value. This is imprecise
as it involves sniffing the error string.
In the case where RequiresReplace is used in the resource schema,
terraform calls Destroy then Create. When Destroy is not complete before
Create starts, it can cause problems with Create. Retry the various
pieces of create until they succeed or timeout.

Removed skip from test cases skipped due to this bug.
While testing update of an application resource with integrations where
RequiresReplace is hit, found an issue with integrations. Removal of an
application, also removes any integrations used by the application. This
causes state confusion for terraform. Adding the replaced_triggered_by
lifecycle info, allows for the integration to also be replaced if the
related application resources are.

List specific schema attributes so that no any change to the application
will trigger the integration as well.
There is no need to test juju error messages in this provider.
Keep skip for state changing too quickly.
We were not failing quickly on deployment errors such as trying to
deploy a subordinate with a unit.
@hmlanigan hmlanigan force-pushed the replace-application-already-exists branch from 9ac9853 to 1c4a657 Compare October 25, 2023 21:11
@hmlanigan
Copy link
Member Author

Rebased to resole conflicts

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.

Application resource plans hitting RequiresReplace can fail with "application already exists"
2 participants