juju / terraform-provider-juju

A Terraform provider for Juju
Apache License 2.0
21 stars 42 forks source link

Incorrect behaviour when multiple models have the same name #504

Open kian99 opened 4 months ago

kian99 commented 4 months ago

Description

The Juju Terraform provider doesn't behave correctly when a user has access to multiple models with the same name. This is mainly relevant to VM models where a model name is only unique according to <ownerName>/<modelName>. On K8s clouds names are unique thanks to namespace rules but if a Juju controller had multiple k8s clouds, this could also be an issue there.

Urgency

Casually reporting

Terraform Juju Provider version

0.12.0

Terraform version

1.8.5

Juju version

3.5.1

Terraform Configuration(s)

terraform {
  required_providers {
    juju = {
      version = "~> 0.12.0"
      source  = "juju/juju"
    }
  }
}

provider "juju" {}

resource "juju_application" "wordpress" {
  name = "wordpress"

  model = "foo"

  charm {
    name = "wordpress"
  }

  units = 1
}

Reproduce / Test

Do the following to setup a controller with 2 users.

- juju bootstrap localhost test
# Change admin password to be able to log back in as the admin
- juju change-user-password
# Create two users https://juju.is/docs/juju/manage-users
- juju add-user alice
- juju add-user bob
# Note: I'm omitting the steps to register and login with the new users
# Grant both users access to the localhost cloud
- juju grant-cloud alice add-model localhost
- juju grant-cloud bob add-model localhost
# Ensure both users have cloud-credentials for the cloud
# Switch to alice
- juju update-credentials localhost --controller test
# Switch to bob 
- juju update-credentials localhost --controller test
# Now create a model with owner bob and grant alice access
- juju add-model foo
- juju grant alice admin foo
# Switch to alice
# Check Alice has only 1 model
- juju models
# Create another model with the same name
- juju add-model foo

Note: To switch users run juju logout then juju login -u <user> -c test.

Now Alice will have access to 2 models with the same name but different owners. At this point it's a little tough to prove the issue without extra debugging in the provider. One can add the following debug line to the provider, compile it locally and view the output.

Add

sc.Tracef(fmt.Sprintf("Model %s found with UUID %s and owner %s", modelSummary.Name, modelSummary.UUID, modelSummary.Owner))

Above this line. Then use the custom provider with the above plan. Before running terraform apply run export TF_LOG="TRACE" to set the debug level for Terraform to trace in order to see the debug logs. They should resemble something similar to,

2024-06-18T13:09:58.581+0200 [TRACE] provider.terraform-provider-juju_v0.12.0: Model foo found with UUID 9da2c4cc-cbdb-4dd0-8f38-f8f8ee571c8f and owner bob: @caller=/home/kian/Source/Work/terraform-provider-juju/internal/juju/client.go:245 @module=juju.client timestamp="2024-06-18T13:09:58.580+0200"
2024-06-18T13:09:58.581+0200 [TRACE] provider.terraform-provider-juju_v0.12.0: Model foo found with UUID 2f3854a7-8dfb-4393-825a-d15cf0da3011 and owner kian: @module=juju.client @caller=/home/kian/Source/Work/terraform-provider-juju/internal/juju/client.go:245 timestamp="2024-06-18T13:09:58.580+0200"

Whatever order is returned by Juju will determine which model the terraform plan will apply to.

hmlanigan commented 4 months ago

@kian99, What do the terraform plans look like in this case? And how are they used? As we have 2 users in the example, please include user in the provider definition block.

kian99 commented 4 months ago

My full TF plan looked as follows, using the local provider,

terraform {
  required_providers {
    juju = {
      version = "0.12.0"
      source  = "registry.terraform.io/juju/juju"
    }
  }
}

provider "juju" {
  controller_addresses = "10.16.149.168:17070"

  username = "bob"
  password = "bob"
}

resource "juju_application" "wordpress" {
  name = "wordpress"

  model = "foo"

  charm {
    name = "wordpress"
  }

  units = 1
}