3
\$\begingroup\$

I am trying to write a program I am calling "terraform cashier." Terraform is a tool released by hashicorp to allow you to codify your infrastructure. I thought it would be useful to know how much your infrastructure would cost you before you deployed it, and have implemented a prototype of that for AWS. I also had to write a pricing data ingestion tool and API to power this particular tool, but those seem to be working fine, so I'd like to keep the review to the cli tool itself.

The repo can be found here.

I do a lot of type casting in the processTerraformFile function. How can I avoid that? Am I processing the terraform files correctly? A particular ugly segment of the function is below. The main goal of the function is to import the data in the terraform templates so that it can be processed inside of cashier. I'm just identifying the resources and counting them.

arrayOfResources, success := decodedOutput["resource"].([]map[string]interface{})

if success == true {
    for _, resource := range arrayOfResources {
        for key := range resource {
            switch key {
            case "aws_instance":
                resourceKeys, resourceKeysSuccess := resource[key].([]map[string]interface{})
                if resourceKeysSuccess == true {
                    for resourceKey := range resourceKeys[0] {
                        instanceType, instanceTypeSuccess := resourceKeys[0][resourceKey].([]map[string]interface{})[0]["instance_type"].(string)
                        if instanceTypeSuccess == true {
                            masterResourceMap = countResource(masterResourceMap, key, instanceType)
                        }
                    }
                }
            default:
                fmt.Println("resource type not recognized: ", key)
            }
        }
    }
}

I wrote some basic tests as well, but decided to not test the main() function. Is this standard? It started to feel strange when I was making API calls in my test.

\$\endgroup\$
  • \$\begingroup\$ As per the How to Ask guidelines, the site standard is to state the purpose of the code, rather than your main concern about the code. If you have a specific question about typecasting, and are treating the code merely as a generic example, then this should be considered a question for Stack Overflow rather than Code Review. \$\endgroup\$ – 200_success Apr 17 '17 at 16:27
1
\$\begingroup\$

Usually, the code is a bit worse, indentation-wise:

if res, ok := decodedOutput["resource"].([]map[string]interface{}); ok {
    for _, resource := range res {
        for key := range resource {
            switch key {
            case "aws_instance":
                if rk, ok := resource[key].([]map[string]interface{}); ok {
                    for resourceKey := range rk[0] {
                        if itype, ok := resourceKeys[0][resourceKey].([]map[string]interface{}); ok {
                            if d, ok := itype[0]["instance_type"].(string); ok {
                                masterResourceMap = countResource(masterResourceMap, key, d)
                            }
                        }
                    }
                }

            default:
                fmt.Println("resource type not recognized: ", key)
            }
        }
    }
}

Now, from a Terraform point-of-view, you already have a semi-assurance that the type you're trying to cast has been cleaned up, this due to how you declare the values of the terraform file. You usually define it with the schema package, so while it's running, you know Terraform already checked the types for you.

The overall I've seen is that providers, for example, do not tests against a true type casting from interfaces, again, due to Terraform pre-checking the information to match the schema definition, so if it is a string but someone passed an int, then Terraform will exit and fail way earlier than reaching your type casting.

\$\endgroup\$
  • \$\begingroup\$ Also, if you still want to check stuff, you're omitting the slice position. If you say resourceKeys[0] then you better make sure there's at least one element. This is not checked somehow by Terraform by default for when you say stuff like resourceKeys[7] but they may check the difference between an empty array / slice vs nothing. \$\endgroup\$ – Patrick D'appollonio Apr 7 '17 at 16:57
  • \$\begingroup\$ You do not need to comment on your own post, you can edit that information into the post. \$\endgroup\$ – Stephen Rauch Apr 7 '17 at 17:02
  • 1
    \$\begingroup\$ Yes, I know. Still, it's an extra comment not even related to the typecasting Bjorn248 was asking, that's why I left it as extra comment and not part of the main comment. First time replying here, but I have a couple of replies in SO. \$\endgroup\$ – Patrick D'appollonio Apr 7 '17 at 23:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.