I am trying an extend Kubernetes operator written in Go to handle Azure Key Vault Secrets that have been disabled. The operator is using the Azure SDK for Go as well as the Azure autorest library.
I am very new to Go and I'm struggling to populate the ServiceError struct when there is an error
The snippet of code I'm looking at is this: (see in context)
response, err := sm.client.GetSecret(ctx, fmt.Sprintf(azureVaultURLFmt, sm.azureVaultName), secretID, "")
if err != nil {
if e, ok := err.(autorest.DetailedError); ok && e.StatusCode.(int) == 404 {
return []byte{}, nil
}
return []byte{}, err
}
At present it handles missing secrets as noted by the 404 http status code. However I want to handle the error situation when you read a disabled secret which surfaces as a 403, and with extra error information in the ServiceError
. However, no matter what I try I haven't managed to figure out how to get at the ServiceError struct.
I tried doing:
if e, ok := err.(azure.ServiceError); ok {
log.V(0).Info("Go an azure service error")
return []byte{}, nil
}
But the code is never called.
Using the original code, I attached the delve debugger with vscode, and I can see that the e
variable had an extra hidden data
variable that appeared to contain both the ServiceError
and DetailedError
struct, but I just can't get at the ServiceError
.
The DetailedError struct has a ServiceError
byte array on it. Am I supposed to manually call UnmarshallJSON
or something like that? I think it's supposed to magically do it for me somehow, but I'm just not sure how.
What am I missing?
CodePudding user response:
So I managed to find a workaround by using a debugger and inspecting the err
object. It isn't particularly pretty, but it does work.
response, err := sm.client.GetSecret(ctx, fmt.Sprintf(azureVaultURLFmt, sm.azureVaultName), secretID, "")
if err != nil {
// We can ignore some errors
if de, ok := err.(autorest.DetailedError); ok {
if re, ok := de.Original.(*azure.RequestError); ok {
if re.ServiceError.Code == "SecretNotFound" {
// Secret not existing is fine, as that means we will create a new secret
return []byte{}, nil
} else if code, ok := re.ServiceError.InnerError["code"].(string); ok && code == "SecretDisabled" {
// Disabled secret also fine, as it means we will create a new version of the secret
return []byte{}, nil
}
}
}
return []byte{}, err
}