How can I use IsNewResource in DiffSuppressFunc? - terraform

Context: I'm developing a TF Provider.
I'm adding the CustomizeDiff function instead however there's a gotcha: if a resource attribute references another attribute (foo = bar.resourcefoo.xyz), it seems to return "" as value on an initial terraform plan run.
Its signature is
// See Resource documentation.
type CustomizeDiffFunc func(context.Context, *ResourceDiff, interface{}) error
and ResourceDiff doesn't have IsNewResource() that ResourceData has. Are there any workarounds to have something similar to IsNewResource()?
In other words, I want something similar to
func SetDiff(ctx context.Context, diff *schema.ResourceDiff, meta interface{}) error {
if diff.IsNewResource() { return nil }
// Otherwise run the check
...
// If we are increasing "size" then the new value must be
// a multiple of the old value.
if new.(int) <= old.(int) {
return nil
}
Some hacks I discovered:
#1:
if diff.Id() == "" { return nil }
#2:
if diff.HasChange()

Related

Shall I save in Terraform state user flag when implementing TF Provider?

Context: I'm building a new TF provider.
There's a foo resource that should optionally allow a user to skip validation when creating an instance of such a resource. Let's call it such attribute enable_validation:
resource "foo" "example" {
name = "abc"
...
enable_validation = true # it's an optional one, should default to false
}
The tricky part is this attribute is specific to foo TF resource so there's no such a attribute in the API which is why I declared it as:
"enable_validation: {
Type: schema.TypeBool,
Optional: true,
Default: false,
ForceNew: true,
},
Now the question is, given the following implementation of fooResource:
...
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
...
...
fooCreate() {
...
if d.Get("enable_validation").(bool) {}
...
return fooRead()
}
fooRead() {
}
How shall I set an attribute enable_validation (if I do need to save it to TF state file at all)? When I do
fooRead() {
...
# do I need this line at all, it looks kinda weird
if err := d.Set("enable_validation"), d.Get("enable_validation"))); err != nil {
return nil, err
}
...
}
there's an issue with import it enable_validation is set to false. Shall I tell users not to set this attribute when importing? It seems like a very popular ask so I'm wondering what's the typical workaround for these sort of attributes.
I found a similar deletion_protection attribute for TF Provider for GCP. Seems like they're explicitly assigning it to default values.
// Explicitly set virtual fields to default values if unset
if _, ok := d.GetOkExists("deletion_protection"); !ok {
if err := d.Set("deletion_protection", true); err != nil {
return fmt.Errorf("Error setting deletion_protection: %s", err)
}
}
That said, GetOkExists seems to be deprecated.
Another (probably a better) example would be ignore_signing_job_failure and it looks like it isn't saved in TF state at all. That said, there's a ignore_signing_job_failure: null in TF state when importing a resource which might be considered as a bug.

How to access a local using a variable in Terraform

I have the following code.
mymodule
variable "senses" {
type = string
}
locals {
sounds = {
"cat" = "meow"
"dog" = ["bark", "woof"]
}
}
output "noise" {
value = local[var.senses]["cat"]
}
call mymodule
module "mymodule" {
source = "../../../modules/mymodule"
senses = "sound"
}
returns error:
Error: Invalid reference
on ../../../modules/mymodule/outputs.tf line 62, in output "noise":
62: value = local[var.senses]["cat"]
The "local" object cannot be accessed directly. Instead, access one of its
attributes.
my code can't seem to handle
value = local[var.senses]["cat"]
Any suggestions on how i can get this to work?
I don't believe it's possible to use a variable to switch which local you're reading. I.e. local[var.senses] is the root of the issue.
If you refactor slightly and put your values inside a single, known, value--such as local.senses it should then let you do a key lookup within that value.
So, if you modify your locals to place your values in a senses key:
locals {
senses = {
"sounds" = {
"cat" = "meow"
"dog" = ["bark", "woof"]
}
}
}
and update your lookup to use that field:
value = local.senses[var.senses]["cat"]
Then I believe it will work, since your are doing a key lookup against a specific local rather than trying to dynamically select the local.

Groovy closure without preceding equal sign prop = {} vs prop {}

I'm trying to create a config file for my java app that can have lazy evaluation, for instance, contain an e-mail template with current date time. I use ConfigSlurper to parse the config file.
For some reason I can't find at https://groovy-lang.org/closures.html the description of the commonly used form (see build.gradle): prop1 { ... } prop2 { ... }. Am I looking at the wrong place?
My tests show that such closures are evaluated immediately and the example above can be rewritten as: prop1 = { ... }() prop2 = { ... }() (notice the parentheses, without them the evaluation is lazy).
I also don't understand why using dots in property without the equal sign cause MissingMethodException: No signature of method: groovy.util.ConfigObject.URL() if I use: server.URL { System.out.println('ccc'); 'asd' } in the example below.
It's disappointing that the choice is completely transparent for Groovy, but you have to check that a value is instance of Closure or GString when using java.
I used this article as the starting point https://blog.mrhaki.com/2009/08/grassroots-groovy-configuration-with.html
// We can group settings.
// The following settings are created:
// app.version, app.setting1, app.setting2, app.setting3, app.date, app.active
app {
System.out.println('aaa')
version = "1.0"
// We can write code to set up settings.
[1, 2, 3].each {
this."setting${it}" = it * 10
}
// We can use Java objects
date = new Date()
active = true
}
server.URL = "http://default"
// Environment specific settings override settings with the
// same name.
environments {
development {
server = { System.out.println('ccc'); 'asd' }
// server.URL = "${-> System.out.println('bbb');new Date()}http://localhost"
}
test {
server.URL = 'http://test:9080'
}
integrationtest {
server.URL = 'http://integrationtest/url'
}
production {
server.URL = 'http://prod/url'
}
}
My tests show that such closures are evaluated immediately and the
example above can be rewritten as: prop1 = { ... }()
Closures are not evaluated immediately. The parens above are causing the closure to be evaluated.
For some reason I can't find at https://groovy-lang.org/closures.html
the description of the commonly used form (see build.gradle): prop1 {
... } prop2 { ... }.
prop1 {} is invoking a method named prop1 and passing a closure as a parameter That code is equivalent to this:
def myClosure = {}
prop1(myClosure)
I also don't understand why using dots in property without the equal
sign cause MissingMethodException: No signature of method:
groovy.util.ConfigObject.URL()
Something like server.URL = 'http://test:9080' is assigning a value (http://test:9080) to a property (server.URL). If you remove the equal sign you are changing the expression fundamentally and then would be invoking a method named URL on an object named server and passing http://test:9080 as a parameter.

Elegant way to check if multiple strings are empty

How can I check if multiple strings are empty in an elegant way? This is how I currently do it:
//if one required field is empty, close the connection
if (registerRequest.Email == "") ||
(registerRequest.PhoneNumber == "")||
(registerRequest.NachName =="") ||
(registerRequest.VorName =="") ||
(registerRequest.Password =="") ||
(registerRequest.VerificationId ==""){
//Could not proceed
w.WriteHeader(UNABLE_TO_PROCEED)
w.Write([]byte("Unable to register account."))
return
}
Note: You may use the solution below if you keep the "is-valid" condition in your handler, and also if you separate your condition into another function or method.
You can create a simple helper function, which has a variadic parameter, and you can call it with any number of string values:
func containsEmpty(ss ...string) bool {
for _, s := range ss {
if s == "" {
return true
}
}
return false
}
Example using it:
if containsEmpty("one", "two", "") {
fmt.Println("One is empty!")
} else {
fmt.Println("All is non-empty.")
}
if containsEmpty("one", "two", "three") {
fmt.Println("One is empty!")
} else {
fmt.Println("All is non-empty.")
}
Output of the above (try it on the Go Playground):
One is empty!
All is non-empty.
Your example would look like this:
if containsEmpty(registerRequest.Email,
registerRequest.PhoneNumber,
registerRequest.NachName,
registerRequest.VorName,
registerRequest.Password,
registerRequest.VerificationId) {
// One of the listed strings is empty
}
Also registerRequest is a kinda long name, it could be shortened to like r. If you can't or don't want to rename it in the surrounding code and if you want to shorten the condition, you could also do something like this:
If registerRequest is a pointer (or interface), you could also write:
if r := registerRequest; containsEmpty(r.Email,
r.PhoneNumber,
r.NachName,
r.VorName,
r.Password,
r.VerificationId) {
// One of the listed strings is empty
}
Actually you can do this even if registerRequest is not a pointer, but then the struct will be copied. If registerRequest is a struct, then you can take its address to avoid having to copy it like this:
if r := &registerRequest; containsEmpty(r.Email,
r.PhoneNumber,
r.NachName,
r.VorName,
r.Password,
r.VerificationId) {
// One of the listed strings is empty
}
As Mario Santini mentioned in comment, a way to increase testability, encapsulate this logic, and decouple it from your handler method (which judging by the number of fields looks like it is at risk of changing at a different rate than your handler) could be to put this logic in a function:
func validRequest(registerRequest ?) bool {
return registerRequest.Email == "" ||
registerRequest.PhoneNumber == "" ||
registerRequest.NachName == "" ||
registerRequest.VorName == "" ||
registerRequest.Password == "" ||
registerRequest.VerificationId == ""
}
This now supports very focused, table driven tests, that can exercise what it means to be a valid request independent of any method involving writing headers.
It allows you to verify the valid/invalid path of your enclosing function, but to have very focused tests here. It also allows you to change what it means to be a valid request and verify it independent of your enclosing function.
You can use a switch:
switch "" {
case registerRequest.Email,
registerRequest.NachName,
registerRequest.Password,
registerRequest.PhoneNumber,
registerRequest.VerificationId,
registerRequest.VorName:
w.WriteHeader(UNABLE_TO_PROCEED)
w.Write([]byte("Unable to register account."))
return
}
https://golang.org/ref/spec#Switch_statements

groovy null safe operator, identifying what was null?

The null safe operator in Groovy is great for reducing code and making things more readable. We can go from this:
def customer = getCustomer(custNo)
if(!customer)
throw new Exception("Invalid customer: ${custNo}")
def policy = customer.getPolicy(policyNo)
if(!policy)
throw new Exception("Invalid policy: ${policyNo}")
def claim = policy.getClaim(claimNo)
if(!claim)
throw new Exception("Invalid claim: ${claimNo}")
..to this...
def claim = getCustomer(custNo)?.getPolicy(policyNo)?.getClaim(claimNo)
But nothing's for free; using null/safe navigation, if claim is null, it's not immediately obvious what caused it: either custNo, policyNo, or claimNo may be invalid.
We could go back and start checking what's null, but that's counterproductive, and actually, it's not even possible since intermediate objects are not stored in variables.
So the question is: Is it possible to identify what was null when chaining method calls using null/safe navigation?
UPDATE
I took another stab at this using dynamic method invocation. It takes an init target (usually a dao) to initialize the object (customer in this case), and a map containing method names as strings (with arguments as values). Using an iterator, invokeChain simply traverses the map (chain); if anything in the chain returns null, identifying the method that caused it becomes trivial.
def invokeChain = { initTarget, chain ->
def obj
chain.eachWithIndex{ it, idx ->
//init obj from dao on first iteration only,
//remaining iterations get from obj itself
obj = (!idx) ? initTarget."$it.key"(it.value) : obj?."$it.key"(it.value)
if(!obj)
throw new Exception("${it.key}(${it.value}) returned null")
}
obj
}
Usage
Mock a customer dao for initTarget...I've inserted null as return type for getClaim(), which should throw an exception.
def static getCustomer = { custNo ->
[ getPolicy: { p ->
[getClaim:{ c ->
null //"Claim #${c}"
}]
}]
}
..using invokeChain, easy as pie:
def claim = invokeChain(this, [getCustomer:123, getPolicy:456, getClaim:789])
...throws exception, as expected:
Exception in thread "main" java.lang.Exception: getClaim(789) returned null
I like this approach because it's compact, readable, and easy to use; what do you think?
I think there is no clear way to do so.
I can be wrong, will check sources later, but safe navigation is a syntax sugar for if statement.
As a hack you can wrap your code with interceptor, trace last method call inside, and then use that info to proide error message.
It will not be cheap, and will cost you some code to realize interception and some performance while running. But you can achieve something like
mayFail("getCusomer", "getPolicy", "getClaim") {
getCustomer(custNo)?.getPolicy(policyNo)?.getClaim(claimNo)
} == "getPolicy" // failed on second step
EDIT: As #tim_yates proved, ?. is a syntax sugar with if construction behind. Thanks Vorg van Geir for the link, I have copied it here, to an answer. He say, it's outdated, and it looks like he is right. I have managed to make ProxyMetaClass work(in Groovy 2.0.6), so given way isn't totally broken. Now I need to specify exact classes to intercept, and I can not find a way to catch inherited method calls.(to simply intercept java.lang.Object)
def logInterceptor = new TracingInterceptor()
logInterceptor.writer = new StringWriter()
def intProxy = ProxyMetaClass.getInstance(Integer)
def stringProxy = ProxyMetaClass.getInstance(String)
intProxy.setInterceptor(logInterceptor)
stringProxy.setInterceptor(logInterceptor)
intProxy.use {
stringProxy.use {
println(("Hello" + "world").size().hashCode())
} }
println(logInterceptor.writer.toString())
All that hell may be wrapped in some utility code, but I highly doubt in necessarity of this. Performance overhead will be awful and some boilerplate code will remain.
The game is not worth the candle.
What about attributions and asserts?
def policy = customer?.policy
def claim = policy?.claim
def number = claim?.number
assert customer, "Invalid customer"
assert policy, 'Invalid policy'
assert claim, 'Invalid claim'
UPDATE:
You already found the solution, but i'd like to contribute with an interceptor idea:
The mock:
def dao = [
getCustomer : { custNo ->
[ getPolicy: { p ->
[getClaim:{ c ->
null //"Claim #${c}"
}]
}]
}
]
The interceptor:
class MethodCallInterceptor {
def delegate
def invokeMethod(String method, args) {
def result = delegate.invokeMethod(method, args)
if (result == null) {
throw new RuntimeException("$method returned null")
}
else {
new MethodCallInterceptor(delegate: result)
}
}
def getProperty(String property ) {
delegate[ property ]
}
void setProperty(String property, value) {
delegate[ property ] = value
}
}
The test:
def interceptedDao = new MethodCallInterceptor(delegate: dao)
try {
interceptedDao.getCustomer(123).getPolicy(456).getClaim(789)
assert false
} catch (e) {
assert e.message.contains( 'getClaim returned null' )
}

Resources