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

terraform modules value of count cannot be computed #12570

Open
zerolaser opened this issue Mar 9, 2017 · 55 comments

Comments

Projects
None yet
@zerolaser
Copy link

commented Mar 9, 2017

I was using terraform modules for IAM user creation, add multiple inline policies and multiple policy_arn's to the user after creation. But now I got an issue where I create an IAM_POLICY and get the arn of this policy and i am trying to add it as policy_arn ="{module.policy.policy_arn}" but i was getting the error, value of 'count' cannot be computed.
My current version of terraform is 0.8.7

module/user/users.tf

variable user {}
variable policy_arn {
   type = "list"
   default = ["default"]
}

variable policy_file {
  type = "list"
  default = ["default"]
}

resource "aws_iam_user" "user" {
  name  = "${var.user}"
}

resource "aws_iam_access_key" "key" {
  user  = "${var.user}"
}

resource "aws_iam_user_policy" "user_policy" {
    count = "${element(var.policy_file, 0) =="default" ? 0: length(var.policy_file)}"
    name = "${element(var.policy_file,count.index)}"
    user = "${var.user}"
    policy = "${file("../policies/${element(var.policy_file,count.index)}.json")}"
    depends_on = ["aws_iam_user.user"]
}

resource "aws_iam_user_policy_attachment" "policy_attach" {
    count = "${element(var.policy_arn, 0) =="default" ? 0: length(var.policy_arn)}"
    user  = "${var.user}"
    policy_arn = "${element(var.policy_arn, count.index)}"
    depends_on = ["aws_iam_user.user"]
}

module/policy/policy.tf

variable policy_file {
  type = "string"
  default = "default"
}

variable description {
  type = "string"
  default = "policy description"
}

resource "aws_iam_policy" "policy" {
    path = "/"
    description = "$(var.description}"
    name = "${var.policy_file}"
    policy = "${file("../policies/${var.policy_file}.json")}"
}

main.tf

module "app_user" {
  source = "../module/user"  
  user = "app-user"     
 policy_file = ["ec2_access", "rds_access" ]
  policy_arn = [ "arn:aws:iam::aws:policy/ReadOnlyAccess","arn:aws:iam::aws:policy/AmazonSQSFullAccess", "${module.test_policy.policy_arn}" ]
}

module "test_policy" {
  source = "../module/policy/policy.tf"
  policy_file = "test_policy"
  description = "Read access to the autoscale event queue"
}

output "policy_arn" {
  value = "${module.test_policy.policy_arn}"
}

when i do terraform plan i was getting the error the aws_iam_user_policy.user_policy: value of 'count' cannot be computed.
now i am not sure. how would i get the arn of the policy created in other module to the current policy_arn to the user.

I tried with terraform 0.9.0 dev its showing the same issue. but if i first apply with target module on the policy then apply for user, Its not throwing any count error. Its working. I might need a way to tell terraform to apply policy module first then apply user module. It should be done with depends_on but i'm not able to call depends_on on other modules. Could we write a null_resource depending on policy and user module depending on null_resource ?

Any suggestions/workarounds or modifications to my modules will be appreciated. thanks.

@mfischer-zd

This comment has been minimized.

Copy link
Contributor

commented Mar 13, 2017

I've seen a similar problem. There seems to be a general issue where the deferred evaluation of the count attribute of any resource declared in a module is performed. In my case, I'm getting a circular dependency error instead of a value of 'count' cannot be computed error.

Here's my case:

module "provisioner" {
  source = "path"
  hosts = "${zipmap("${google_compute_instance.consul_server.*.network_interface.0.access_config.0.assigned_nat_ip}", "${google_compute_instance.consul_server.*.network_interface.0.address}")}"

Module source:

variable "hosts" {
  type = "map"
}

resource "null_resource" "provision_consul" { 
   count = "${length(keys(var.hosts))}"   
   # etc
}

If I do this, I get:

Error configuring: 1 error(s) occurred:

* Cycle: module.provisioner.var.hosts, module.provisioner.null_resource.provision_consul (destroy), google_compute_instance.consul_server (destroy), google_compute_instance.consul_server

However, if I simply change the count in the module to a number, it works fine.

My current workaround is to declare a server_count variable in the calling template and pass it to the count attributes in both the calling template (literally) and the module (via a separate variable):

variable "server_count" {
  default = "3"
}

resource "google_compute_instance" "consul_server" {
  count = "${var.server_count}"
  ...
}

module "provisioner" {
  source = "../modules/provisioner"
  hosts = "${zipmap("${google_compute_instance.consul_server.*.network_interface.0.access_config.0.assigned_nat_ip}", "${google_compute_instance.consul_server.*.network_interface.0.address}")}"
  count = "${var.server_count}"
}

Provisioner:

resource "null_resource" "provision_consul" {
  count = "${var.count}"
  ...
}
@beanaroo

This comment has been minimized.

Copy link

commented Mar 13, 2017

I was just hit with a similar problem:

resource "aws_security_group_rule" "ec2_allow_ssh" {
    count             = "${var.vpc["ssh_enabled"] == "true" ? 1 : 0 }"
    type              = "ingress"

    from_port         = 22
    to_port           = 22
    protocol          = "tcp"
    cidr_blocks       = ["${split(",", var.vpc["ssh_allowed_cidrs"])}"]

    security_group_id = "${aws_security_group.nodejs_ec2.id}"
}

Throws a circular dependency error:

Errors:

  * 1 error(s) occurred:

* Cycle: module.preview_vpc.aws_subnet.public (destroy), module.preview_vpc.aws_subnet.public, module.preview_vpc.output.public_subnets, module.preview_ics-api-nodejs.var.vpc, module.preview_ics-api-nodejs.aws_security_group_rule.ec2_allow_ssh (destroy), module.preview_vpc.aws_subnet.private (destroy), module.preview_vpc.aws_subnet.private, module.preview_vpc.output.private_subnets

But if I hard code a 1 or 0, it works.

Thanks for the workaround @mfischer-zd. It's not pretty but seems we have no choice at the moment.

@myroslav

This comment has been minimized.

Copy link

commented Mar 23, 2017

It look like all of the calculated parameters that influence the count should land in the terraform.tfstate state first and this can be done with manual selective terraform apply -target=.... After all dependencies are created and cached in tfstate, subsequent terraform plan does not require any manual dependency management.

@LinusU

This comment has been minimized.

Copy link
Contributor

commented Apr 4, 2017

I think I have a similar problem, it seems like my count worked when I had

resource "aws_route53_record" "dns" {
  count = "${length(var.domains)}"

  // ...
}

but when I added this (👇) ternary expression, it doesn't work when length(var.ips) evaluates to more than 0...

resource "aws_route53_record" "dns" {
  count = "${length(var.ips) > 0 ? length(var.domains) : 0}"

  // ...
}
@tomyan

This comment has been minimized.

Copy link

commented Apr 19, 2017

We're having this issue as well, similar to the initial report (trying to pass an iam policy document into a module that references resources outside the module). If the resources already exist then it seems to work (in our staging environment the resources were created in one update and the policy added in a subsequent one, which worked), but if the resources don't exist (as we found in our production environment where both updates were applied at once) then we get the value of 'count' cannot be computed error.

@hazim1093

This comment has been minimized.

Copy link

commented Jun 8, 2017

I'm facing a similar issue with terraform version 0.9.6 as well

The weird thing is that im using this

count = "${(signum(length(var.myVar)) + 1) % 2}"

in one module and it seems to be working fine there, the same expression in another module with another variable inside results in the value of 'count' cannot be computed error

Another thing that confuses me is that, I changed the line to

count = "${length(var.myVar) > 0 ? 0 : 1}"

And it worked for the first time after doing this, no errors everything created successfully, but after that time, doing this also results in the same error.

Is there a workaround to this?

@hazim1093

This comment has been minimized.

Copy link

commented Jun 8, 2017

apparently I changed

count = "${length(var.myVar) > 0 ? 0 : 1}"

to (another variable)

count = "${length(var.myVar2) > 0 ? 0 : 1}"

and it is not complaining (for now)

@ketzacoatl

This comment has been minimized.

Copy link
Contributor

commented Jun 18, 2017

This is still a bug / problem with 0.9.8.

Here is my version the error from a VPC module's test env:

* module.vpc.module.public-gateway.aws_route_table_association.public: aws_route_table_association.public: value of 'count' cannot be computed
* aws_instance.web: aws_instance.web: value of 'count' cannot be computed
@goetas

This comment has been minimized.

Copy link

commented Jun 19, 2017

duplicate of #10857

@ketzacoatl

This comment has been minimized.

Copy link
Contributor

commented Jun 21, 2017

While I can understand the choice to not allow length() on computed values.. that choice, coupled with an inability to define module dependencies, leaves us high and dry for legit use of length():

module "nat-gateway" {
  source             = "../nat-gateways"
  vpc_id             = "${module.vpc.id}"
  name_prefix        = "${var.name_prefix}"
  nat_count          = "${length(module.private-subnets.ids)}"
  public_subnet_ids  = ["${module.public-subnets.ids}"]
  private_subnet_ids = ["${module.private-subnets.ids}"]
  extra_tags         = "${var.extra_tags}"
}

This fails if the private-subnets module hasn't already been applied.. so you need to run tf apply multiple times (using -target carefully).

Issues like this make it difficult to use Terraform modules.

@apparentlymart

This comment has been minimized.

Copy link
Member

commented Jun 21, 2017

Hi all! Thanks for the great discussion here.

The current approach was added as a compromise to enable the use of data source results to be used in count, as long as the data source is resolvable during the plan phase. We know that this isn't fully general and in particular doesn't work well for resource attributes, but didn't want to delay for the fully-general solution when an intermediate state was possible.

Something like #4149 will be the eventual solution to this. This sort of workflow/architecture change we want to approach carefully, but we do intend to address this problem once we've worked though the implications and found a solid design for it.

@rorybrowne

This comment has been minimized.

Copy link

commented Jul 27, 2017

Hi @apparentlymart

What exactly is the current approch?

I'm using an external data source which massages some of my input from what is realtively easy for humans to configure, to what is relatively easy to express in terraform, and count doesn't seem to like the result of it.

My external data source only reads in data that has been passed as input variables.

i've tried this in both Terraform 0.9.9 and 0.9.11.

@apparentlymart

This comment has been minimized.

Copy link
Member

commented Jul 27, 2017

The current constraint is that count may only use values that can be known at plan time. There are a few ways this can be true:

  • The main way is for the count to refer directly to a data resource that doesn't have any dependency on a managed resource (a resource block in config). In this case, Terraform is able to read the data during the "refresh" step, which happens before the plan is produced, and thus the latest data is available to Terraform during the plan.
  • A more fiddly way is to use the -target option to request that Terraform should create or update a particular resource in isolation first, thus making it available in state for use as count on a subsequent run. This allows count to refer to a managed resource attribute, but requires this extra -target step first. (Automating this two-step process is what #4149 is about.)
  • Both of the above approaches can work indirectly via module variables too, with the same constraints: the value assigned to the module variable by the caller must be known at plan time, since the "known-ness" of the value propagates to the child module.

@rorybrowne if your count expression is referring only to attributes of a data resource then the first of the items above should apply, unless that data resource itself depends on a managed resource. A data resource that depends on a managed resource can't be read until the managed resource is know, so it ends up behaving like the second item above instead. If you are able to share the relevant subset of your config, I may be able to spot the reason why things aren't working as expected in your case.

@rorybrowne

This comment has been minimized.

Copy link

commented Jul 28, 2017

Thanks @apparentlymart

I tried to reproduce it with a sample that I could send, but the reproduction didn't work. Some detective work later, it turned out that my external resource had some syntax errors.

Having that said, it would've been nice if I got a "your external data resource is fu...barred", rather than a "you can't use count" type error message. I'll see if I can recreate that problem ( unfortunatly I didn't take a commit at the time ), and do up a bug report.

@YehudaCohen

This comment has been minimized.

Copy link

commented Sep 18, 2017

@apparentlymart Thanks for taking the time to explain these proposed approaches. To me using the -target manually means that doing this at scale becomes unwieldy. Is there any update on when this is expected to be automated? Issue 4149 doesn't seem to have much activity.

@kerin

This comment has been minimized.

Copy link

commented Sep 22, 2017

I'm really baffled by the behaviour of count at this point. I'm trying to use CoreOS's kubernetes module from the Terraform registry, which has a couple of module variables, tectonic_aws_external_master_subnet_ids and tectonic_aws_external_worker_subnet_ids, which are ultimately used as part of a ternary expression in a count attribute:

data "aws_subnet" "external_worker" {
  count = "${var.external_vpc_id == "" ? 0 : length(var.external_worker_subnets)}"
  id    = "${var.external_worker_subnets[count.index]}"
}

data "aws_subnet" "external_master" {
  count = "${var.external_vpc_id == "" ? 0 : length(var.external_master_subnets)}"
  id    = "${var.external_master_subnets[count.index]}"
}

Initially I tried to pass in the output from another pre-existing module:

tectonic_aws_external_master_subnet_ids = ["${module.aws_vpc.private_subnet_ids}"]
tectonic_aws_external_worker_subnet_ids = ["${module.aws_vpc.private_subnet_ids}"]

which raises this error on plan:

* module.kubernetes.module.vpc.data.aws_subnet.external_master: data.aws_subnet.external_master: value of 'count' cannot be computed
* module.kubernetes.module.vpc.data.aws_subnet.external_worker: data.aws_subnet.external_worker: value of 'count' cannot be computed

Then I tried splitting this into two separate resources and referencing the existing module's output as remote state:

tectonic_aws_external_master_subnet_ids = ["${data.terraform_remote_state.env.aws_vpc.private_subnet_ids}"]
tectonic_aws_external_worker_subnet_ids = ["${data.terraform_remote_state.env.aws_vpc.private_subnet_ids}"]

but received the same error. And then out of frustration I tried using a literal list:

tectonic_aws_external_master_subnet_ids = ["subnet-fe5727b7", "subnet-f7c471ac", "subnet-07a1c860"]
tectonic_aws_external_worker_subnet_ids = ["subnet-fe5727b7", "subnet-f7c471ac", "subnet-07a1c860"]

And still get the same error:

* module.kubernetes.module.vpc.data.aws_subnet.external_master: data.aws_subnet.external_master: value of 'count' cannot be computed
* module.kubernetes.module.vpc.data.aws_subnet.external_worker: data.aws_subnet.external_worker: value of 'count' cannot be computed

So at this point it looks to me like you either can't use a ternary expression in a count attribute, or maybe even nothing other than an integer literal or a reference to a terraform_resource.*.id? Yet Terraform's docs give an example of using a variable in a ternary expression in a count attribute:

A common use case for conditionals is to enable/disable a resource by conditionally setting the count:

resource "aws_instance" "vpn" {
  count = "${var.something ? 1 : 0}"
}

So is this broken? Are the docs wrong? Or am I missing something? Because with this current behaviour it's not clear what the intention behind the Terraform module registry is, if passing output from one module to the input of another causes problems with basic constructs like count.

grahamlyons added a commit to mergermarket/tf_route53_dns that referenced this issue Oct 3, 2017

grahamlyons added a commit to mergermarket/tf_frontend_router that referenced this issue Oct 3, 2017

Switch the alias flag on
This is now required to work around hashicorp/terraform#12570

JIRA: PLAT-1117

afda16 added a commit to alphagov/govuk-aws that referenced this issue Dec 13, 2017

AWS node_group module add TG length parameter
The way in which we use the 'lb' and 'node_group' modules,
the `instance_target_group_arns` value is the output of the
lb module. We tried using the length of the value in a count
parameter which is not supported by Terraform (because it's computed).

There are some issues in the Terraform project regarding this limitation,
for instance: hashicorp/terraform#12570

In some cases it's recommended to use `-target` when applying Terraform
changes to create the LB resources before the node_group, but this is
quite difficult to integrate in our solution because we don't have a
proper CD pipeline yet.

At this point, our way of getting around this issue is by creating a
`_length` variable with the expected length of instance_target_group_arns,
that we calculate outside the module.

This is aligned with the solution used with private networks and
NAT instances in `terraform/modules/aws/network/private_subnet/main.tf`.

afda16 added a commit to alphagov/govuk-aws that referenced this issue Dec 14, 2017

AWS node_group module add TG length parameter
The way in which we use the 'lb' and 'node_group' modules,
the `instance_target_group_arns` value is the output of the
lb module. We tried using the length of the value in a count
parameter which is not supported by Terraform (because it's computed).

There are some issues in the Terraform project regarding this limitation,
for instance: hashicorp/terraform#12570

In some cases it's recommended to use `-target` when applying Terraform
changes to create the LB resources before the node_group, but this is
quite difficult to integrate in our solution because we don't have a
proper CD pipeline yet.

At this point, our way of getting around this issue is by creating a
`_length` variable with the expected length of instance_target_group_arns,
that we calculate outside the module.

This is aligned with the solution used with private networks and
NAT instances in `terraform/modules/aws/network/private_subnet/main.tf`.

wking added a commit to wking/openshift-installer that referenced this issue Sep 18, 2018

modules/aws/bootstrap: Add elbs_length
To work around Terraform's limitations on length() of computed lists
at plan-time [1].  By avoiding the generated resources and just
computing the number of elastic load-balancers based on our input
counts, we avoid confusing Terraform and getting [2]:

  * module.bootstrap.aws_elb_attachment.bootstrap:
    aws_elb_attachment.bootstrap: value of 'count' cannot be computed

The value of 3 or 2 comes from:

* One internal LB (either aws_elb.api_internal or aws_elb.api_external),
* One aws_elb.console, and
* Possibly one aws_elb.tnc.

[1]: hashicorp/terraform#12570 (comment)
[2]: https://storage.googleapis.com/origin-ci-test/pr-logs/pull/openshift_installer/268/pull-ci-openshift-installer-e2e-aws/316/build-log.txt

wking added a commit to wking/openshift-installer that referenced this issue Sep 19, 2018

modules/aws/bootstrap: Add elbs_length
To work around Terraform's limitations on length() of computed lists
at plan-time [1].  By avoiding the generated resources and just
computing the number of elastic load-balancers based on our input
counts, we avoid confusing Terraform and getting [2]:

  * module.bootstrap.aws_elb_attachment.bootstrap:
    aws_elb_attachment.bootstrap: value of 'count' cannot be computed

The value of 3 or 2 comes from:

* One internal LB (either aws_elb.api_internal or aws_elb.api_external),
* One aws_elb.console, and
* Possibly one aws_elb.tnc.

[1]: hashicorp/terraform#12570 (comment)
[2]: https://storage.googleapis.com/origin-ci-test/pr-logs/pull/openshift_installer/268/pull-ci-openshift-installer-e2e-aws/316/build-log.txt

wking added a commit to wking/openshift-installer that referenced this issue Sep 21, 2018

modules/aws/bootstrap: Add elbs_length
To work around Terraform's limitations on length() of computed lists
at plan-time [1].  By avoiding the generated resources and just
computing the number of elastic load-balancers based on our input
counts, we avoid confusing Terraform and getting [2]:

  * module.bootstrap.aws_elb_attachment.bootstrap:
    aws_elb_attachment.bootstrap: value of 'count' cannot be computed

The value of 2 comes from:

* One internal LB (either aws_elb.api_internal or aws_elb.api_external) and
* One aws_elb.console.

[1]: hashicorp/terraform#12570 (comment)
[2]: https://storage.googleapis.com/origin-ci-test/pr-logs/pull/openshift_installer/268/pull-ci-openshift-installer-e2e-aws/316/build-log.txt
@andresvia

This comment has been minimized.

Copy link

commented Sep 25, 2018

Another note about the issue.

data "aws_ssm_parameter" "count" {
  name = "${var.ssm_path}/count"
}
resource "aws_elasticache_replication_group" "main" {
  count = "${data.aws_ssm_parameter.count.value}"
  // ...
}

This works on the root module, but I get the value of 'count' cannot be computed when included (i.e. non root module).

@pixelicous

This comment has been minimized.

Copy link

commented Oct 3, 2018

Amazingly this is open for over a year now 🤦‍♂️

@Crapworks

This comment has been minimized.

Copy link

commented Oct 3, 2018

I just hit this as well... Modules become more and more useless for me. Every time I try putting my code into a module, after a few hours I'm reading github issues that say "sorry, that's not possible". (just as a few examples: using count with modules, using depends_on with modules and now this). Calling hardcoding count a workaround is like a programming language telling the programmer "sorry, we don't support loops, just copy&paste your code as often as you want to run it"

@HighwayofLife

This comment has been minimized.

Copy link

commented Oct 3, 2018

@Crapworks I use count with modules in almost all of my infrastructure. You just have to use one of the listed workarounds.

Terraform 0.12 will fix all these problems. Due to be released soon.

@apparentlymart

This comment has been minimized.

Copy link
Member

commented Oct 26, 2018

Hi all!

By now this issue is covering quite a number of different root problems that all happen to have the same symptoms. The root problem that Terraform cannot support a computed count will unfortunately remain true until #4149 can be addressed in a later release, but in the v0.12-alpha1 the most common cases where Terraform would unnecessarily consider a value to be "computed" have been addressed.

For example, several people in this thread were (understandably) surprised that Terraform would consider an expression like length(aws_instance.foo.*.id) to be computed, since Terraform ought to know how many instances there are of aws_instance.foo. In Terraform v0.12.0-alpha1 I've verified that this is indeed now working as expected:

resource "null_resource" "a" {
  count = 2
}

resource "null_resource" "b" {
  count = length(null_resource.a)
}

output "ids" {
  value = null_resource.b.*.id
}
$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # null_resource.a[0] will be created
  + resource "null_resource" "a" {
      + id = (known after apply)
    }

  # null_resource.a[1] will be created
  + resource "null_resource" "a" {
      + id = (known after apply)
    }

  # null_resource.b[0] will be created
  + resource "null_resource" "b" {
      + id = (known after apply)
    }

  # null_resource.b[1] will be created
  + resource "null_resource" "b" {
      + id = (known after apply)
    }

Plan: 4 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

null_resource.a[0]: Creating...
null_resource.a[1]: Creating...
null_resource.a[1]: Creation complete after 0s [id=8551500515924767906]
null_resource.a[0]: Creation complete after 0s [id=1112095521491468891]
null_resource.b[0]: Creating...
null_resource.b[1]: Creating...
null_resource.b[1]: Creation complete after 0s [id=8431205028446970269]
null_resource.b[0]: Creation complete after 0s [id=1368916686735775390]

Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

Outputs:

ids = [
  "1368916686735775390",
  "8431205028446970269",
]

Note that the terminology "computed" has now been replaced with "unknown" in v0.12, with unknown values showing as "(known after apply)" in the rendered diff.

Along with this specific case, a list or map that contains an unknown element can now pass through a module boundary (in via a variable or out via an output) as-is, without the entire collection itself becoming unknown as we saw in v0.11 and prior. The appearance of this error should therefore be in a much smaller set of cases than before.


The v0.12.0-alpha1 also includes a more detailed error message for the remaining cases where count is unknown.

In a future minor release we also intend to make this do one more level of analysis to find the specific reference that is unknown and indicate it directly, ideally also then offering an exact -target option value that would resolve it, but sadly we were not able to fit the remaining work for that into the initial v0.12.0 release scope due to unexpected extra complexity elsewhere. In the mean time, we hope that this new error message at least gives some better context about the problem and some broad guidance on where to start with working around it until #4149 is resolved, which must wait for a subsequent major release due to the non-trivial graph builder adjustments it requires.

@mcapuccini

This comment has been minimized.

Copy link

commented Nov 19, 2018

I have figured out a workaround for 0.11.x. I create a list of resources IDs, which are dynamically computed, and then I attach a local provisioner to the dependent resource which just runs a bash comment with the interpolated list. Example follows:

# Compute dynamic dependencies for RKE provisioning step (workaround, may be not needed in 0.12)
locals {
  rke_cluster_deps = [
    "${join(",",module.master.prepare_nodes_id_list)}",
    "${join(",",module.worker.prepare_nodes_id_list)}",
    "${join(",",module.master.associate_floating_ip_id_list)}",
    "${join(",",module.master.allowed_ingress_id_list)}",
    "${join(",",module.worker.allowed_ingress_id_list)}",
    "${join(",",module.secgroup.rule_id_list)}",
    "${module.network.interface_id}",
  ]
}

# Provision RKE
resource rke_cluster "cluster" {
  nodes_conf = ["${concat(module.master.node_mappings,module.worker.node_mappings)}"]

  bastion_host = {
    address      = "${element(module.master.public_ip_list,0)}"
    user         = "${var.ssh_user}"
    ssh_key_path = "${var.ssh_key}"
    port         = 22
  }

  ignore_docker_version = "${var.ignore_docker_version}"

  # Workaround: make sure resources are created and deleted in the right order
  provisioner "local-exec" {
    command = "# ${join(",",local.rke_cluster_deps)}"
  }
}

# Write kubeconfig.yaml
resource local_file "kube_cluster_yaml" {
  filename = "./kubeconfig.yml"
  content  = "${rke_cluster.cluster.kube_config_yaml}"
}

I do this mostly because I want rke_cluster to be dependent on resources inside modules, but you can compute other stuff and attach it in the same way.

@tim-baker115

This comment has been minimized.

Copy link

commented Nov 26, 2018

Hey Mcapuccini, I'm also using rancher and trying (hard) to create some valid and dynamic yaml (I'm trying to use hostname). I'm not using ansible so my config may differ from yours. Can you offer any support at all?

@mcapuccini

This comment has been minimized.

Copy link

commented Nov 26, 2018

Hi @tim-baker115. I got it working eventually: https://github.com/mcapuccini/terraform-openstack-rke. It's still work in progress, but feel free to give it a try. If you have any problem you can come back to me via issue. I am not creating the YAML, but I am using: https://github.com/yamamoto-febc/terraform-provider-rke.

@benmenlo

This comment has been minimized.

Copy link

commented Jan 8, 2019

For me I am literally using the example the terraform doc uses and it is failing with the "count can not be computed error":

data "aws_subnet_ids" "existing" {
  vpc_id = "${var.udb_vpc}"
}

data "aws_subnet" "computed" {
   count = "${length(data.aws_subnet_ids.existing.ids)}"
   id    = "${data.aws_subnet_ids.existing.ids[count.index]}"
}

resource "aws_elb" "udb_elb" {
  name            = "${var.role}-${var.mode}-${var.version}"
  internal        = false
  security_groups = ["${aws_default_security_group.default.id}", "${aws_security_group.udb_service_access.id}", "${aws_security_group.udb_frontend_access.id}"]
  subnets         = ["${data.aws_subnet.computed.ids}"]

  listener {
    instance_port     = "${var.api_port}"
    instance_protocol = "TCP"
    lb_port           = "${var.api_port}"
    lb_protocol       = "TCP"
  }

  listener {
    instance_port     = "${var.frontend_port}"
    instance_protocol = "TCP"
    lb_port           = "${var.frontend_port}"
    lb_protocol       = "TCP"
  }

  health_check {
    healthy_threshold   = 3
    unhealthy_threshold = 3
    timeout             = 5
    target              = "TCP:${var.frontend_port}"
    interval            = 30
  }

  cross_zone_load_balancing   = true
  idle_timeout                = 60
  connection_draining         = true
  connection_draining_timeout = 300
}

@tomasaschan

This comment has been minimized.

Copy link

commented Jan 18, 2019

@apparentlymart I'm hitting the symptoms described in this issue, but I'm not sure the root cause is the same as what the workarounds suggested above indicate.

Given the following config:

resource "azurerm_app_service" "backend" {
    # omitted for brevity
}

resource "azurerm_postgresql_server" "transferapi-db" {
    # omitted for brevity
}


locals {
  db_ip_whitelist = ["${split(",", azurerm_app_service.backend.possible_outbound_ip_addresses)}"]
}

resource "azurerm_postgresql_firewall_rule" "db-backend" {
  count = "${length(local.db_ip_whitelist)}"
  name  = "backend"

  depends_on = ["azurerm_app_service.backend", "azurerm_postgresql_server.db"]

  resource_group_name = "${azurerm_resource_group.backend.name}"
  server_name         = "${azurerm_postgresql_server.db.name}"
  start_ip_address    = "${element(local.db_ip_whitelist, count.index)}"
  end_ip_address      = "${element(local.db_ip_whitelist, count.index)}"
}

I expect to fail in the ways mentioned above when the app service is not yet provisioned. However, I'm seeing this error even after first creating the app service using -target=.

I can also verify that the property is indeed known and present in my state, by looking at

$ terraform state show azurerm_app_service.backend | grep possible
possible_outbound_ip_addresses                   = <a redacted comma-separated list of addresses>

So if this is present in my state, why can count not be computed?

I've also tried inlining the expression instead of having it in a local variable, but that made no difference.

samcrang added a commit to alphagov/gsp-terraform-ignition that referenced this issue Mar 1, 2019

Workaround issue with calculating length of computed resources
We have to pass the number of subnets around (rather than dynamically
counting them) because of an issue in Terraform:

hashicorp/terraform#12570

Without this we see the following error message when `terraform
apply`ing from scratch:

```
Error: Error refreshing state: 1 error(s) occurred:

* module.hsm.data.aws_subnet.vpc: data.aws_subnet.vpc: value of 'count'
cannot be computed
```

If the cluster has already been spun up and the HSM module included at a
later date then the Terraform would apply cleanly in its current state.

This may be end up being resolved in Terraform 0.12 when it is released.

devoptimist added a commit to devoptimist/terraform-windows-workstation-tools that referenced this issue May 19, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.