unexpected type error after terraform 0.12 migration - module

I am in the process of migrating my terraform 0.11 configuration to terraform 0.12.5.
The migration (using 0.12upgrade) went relatively smoothly, but then I encountered this error during the next plan
Error: Invalid value for module argument
on main.tf line 72, in module "foo":
72: subnet_ids = module.vpc.subnet_ids
The given value is not suitable for child module variable "subnet_ids"
defined at ../../modules/foo/main.tf:10,1-30: element 0: string
required.
The module foo has a (migrated) variable declaration subnet_ids that looks like this:
variable "subnet_ids" {
type = list(string)
}
while the vpc module has an output declaration that is declared like this:
output "subnet_ids" {
value = [aws_subnet.private.*.id]
}
It seems that if I relax the type constraint on the foo module the error goes away.
However, is this the correct thing to do. After all, isn't the output of the vpc module actually a list of strings? How do I check the type of the vpc output variable?
Update: relaxing the type constraint allows the first part of the validation to succeed, but merely causes problems for the consuming module when the variable is applied as per this output
Error: Incorrect attribute value type
on ../../modules/foo/main.tf line 350, in resource "aws_ecs_service" "api":
350: subnets = var.subnet_ids
Inappropriate value for attribute "subnets": incorrect set element type:
string required.
So the question is: what am I doing wrong when I am defining the output value? How to I ensure the output value is a list of strings so that I don't get the original error? How can I inspect the type of vpc.subnet_ids?

Turns out, I needed to change this:
output "subnet_ids" {
value = [aws_subnet.private.*.id]
}
to this:
output "subnet_ids" {
value = aws_subnet.private[*].id
}

If you have list of subnet_ids you need to add like below
subnet_ids = flatten([module.vpc.public_subnets, module.vpc.private_subnets])
Check this answer as well

In the variable files mention the "subnet_ids" as a list.
variable "subnet_ids" {
type = list
default = []
}
Then in your module grab the subnet list as following
subnet_ids = [var.subnet_ids[0], var.subnet_ids[1]]

Related

What is the variable type for {"message":"ok"} in terraform

I'm writing a terraform module for GCP uptime checks and I need to filter {"message":"ok"} in response body.
Need to pass {"message":"ok"} as a variable, but still cannot find the suitable variable type for it.
I tried complex variable types. But issue not resolved yet
I think you can use a map as variable, example :
variable.tf file :
variable "message" {
description = "Message"
type = map
default = {
"message" = "ok"
}
}
Display the message value in the outputs.tf file for example :
output "message_value" {
value = var.message["message"]
}
Thanks all This is resolved by using jsonencode({ "message" : "ok" })

How do i load a local variable inside a module in Terraform?

I have a locals.tf file with:
locals {
labels = {
mockup = "duration is set 555"
}
}
And a module called "TEST" where i define a GCP bucket resource:
resource "google_storage_bucket" "my_bucket_2" {
...
labels = var.labels_bucket
}
I also have a variables.tf file inside the TEST module:
variable "labels_bucket" {}
Inside the main.tf file i loaded the module like this:
module "test" {
source = "./TEST"
labels_bucket = local.labels
}
I expected the variable to get the value of the local one, instead i get this error inside the module:
googleapi: Error 400: Invalid argument, invalid
How do i map these values?
Thank you!
Simple, Because it's issue with value of the map. Nothing to do with terraform.

How to pass argument to karate.call [duplicate]

This question already has an answer here:
Calling feature file with multiple arguments
(1 answer)
Closed 1 year ago.
I am passing argument to karate.call as following:
...getting object by name
* def id = response.content[0].id
And eval if (size(response.content) == 1) { karate.call('delete/delete-object.feature', id); }
However, I am getting: unexpected feature call arg type: class java.lang.String. Should I somehow cast the argument at first?
I am just creating the scenario which should at first delete the object if existing. Deletion I am doing in delete-object.feature.
Please read the docs, the (single) call argument always has to be a JSON or array of JSONs (unless it is a call to a JS function): https://github.com/intuit/karate#calling-other-feature-files
It is easy to shape, e.g. : * def arg == { id: '#(id)' }
Just for the sake of reference, I'm posting a solution here.
* def id = response.content[0].id
And eval if (size(response.content) == 1) { karate.call('delete/delete-object.feature') { id : '#(id)' } ; }
Inside delete-object.feature file, just use id to access that value. Keep in mind that there's a strange behavior in karate. If you pass in an object such as " { car: '#(carobject)'} ", you cannot access that object by calling "car" inside the feature file you pass this object in. You need to use the object name itself, not the attribute name. So, in this case, it would be "carobject". Hope that helps

Empty object with union type in graphQL

When I' using union type in my graphQL schema I use it typically like this:
const documentTypeDefs = gql`
union TestType = TypeExample1 | TypeExample2
type Document {
exampleKey: TestType
}
`
Then I resolve it like this:
TestType: {
__resolveType(obj) {
if(obj.property1) {
return 'TypeExample1';
}
if(obj.property2) {
return 'TypeExample2';
}
return null;
},
}
But sometimes I'm getting empty object in my resolving function (ie. obj is {}). I thought returning null or undefined will do the job but unfortunately I'm getting error:
"Abstract type ItemsType must resolve to an Object type at runtime for field Document.exampleKey with value {}, received \"{}\". Either the ItemsType type should provide a \"resolveType\" function or each possible type should provide an \"isTypeOf\" function."
How can I resolve empty object then?
Thank you!
If an empty object is being passed to __resolveType, that means your field is resolving to an empty object. That means either the value being returned inside your resolver is an empty object, or else the Promise returned is resolving to one.
If you're working with a field that returns a List, it's also possible for just one of the items being returned to be an empty object. This is particularly likely when working with MongoDB if one of the documents you're getting is actually empty or at least missing the fields you've specified in your mongoose schema.

SharePoint 2010: Error Mapping to Picture Hyperlink with SPMetal

Whenever I have a column of type hyperlink with the format set for pictures, I get an error whenever there is actually a value in that column.
The exception it throws is "Specified cast is not valid".
My thought is that the problem is either here (the FieldType being set to Url):
[Microsoft.SharePoint.Linq.ColumnAttribute(Name = "FOO", Storage = "FOO_", FieldType = "Url")]
public string FOO
{
get
{
return this._FOO;
}
set
{
if ((value != this._FOO))
{
this.OnPropertyChanging("FOO", this._FOO);
this._FOO = value;
this.OnPropertyChanged("FOO");
}
}
}
Or here (it being cast to a string):
private string _FOO;
But I'd have no idea what the proper values for either of those fields should be.
Any help would be greatly appreciated.
It works whenever this field does not have data in it and I JUST used SPMetal to generate the class, so I'll get the two most obvious questions out of the way.
Link to the answer:
https://mgreasly.wordpress.com/2012/06/25/spmetal-and-workflow-associations/
Turns out it is a known bug when mapping lists that have associated workflows.
SPMetal assigns it as a nullable integer when it's supposed to be an Object, hence the cast error.
Workaround: manually edit the mappings to make the type it returns an object or ignore the column by using a parameter map.