Caused by: com.google.api.client.http.HttpResponseException: 400 Bad Request
{
"error": {
"errors": [
{
"domain": "global",
"reason": "invalid",
"message": "Invalid value for field 'resource.allowed[0].IPProtocol': ''. Invalid IP protocol specification."
}
],
"code": 400,
"message": "Invalid value for field 'resource.allowed[0].IPProtocol': ''. Invalid IP protocol specification."
}
}
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1070)
at com.google.api.gax.httpjson.HttpRequestRunnable.run(HttpRequestRunnable.java:130)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Field referred to in runtime error is defined programmatically using the appropriate class builder function. Error indicates a null string was provided in the HTTP request.
String project = "project/foo";
Allowed allowed = Allowed.newBuilder().setIPProtocol("tcp").addPorts("80").build();
Firewall firewallResource = Firewall.newBuilder().setName("test-rule").addAllowed(allowed).build();
firewallClient.insertFirewall(project, firewallResource);
API reference indicates that "tcp" is a valid value.
Fields | Description
------ | ------
allowed[].IPProtocol | string
The IP protocol to which this rule applies. The protocol type is required when creating a firewall rule. This value can either be one of the following well known protocol strings (tcp, udp, icmp, esp, ah, ipip, sctp), or the IP protocol number.
Inspection of Allowed.java revealed there may be a mismatch between the field name strings used by Allowed.java and other parts of the code.
@Override
public Object getFieldValue(String fieldName) {
if (fieldName.equals("iPProtocol")) {
return iPProtocol;
}
if (fieldName.equals("ports")) {
return ports;
}
return null;
}
In the code runtime error message and the API reference, the field is referred to as "IPProtocol", with an upper case "I" in "IP". If getFieldValue("IPProtocol") were called, it would return null.
This seems to be an issue with GAPIC Generator for discovery-based compute api:
Generated classes missing the json property mapping attribute e.g. @Key('..') or similar.
Here gapic-generator generates: Allowed.java-->{String ipProtocol} without annotation @Key("IPProtocol") or simillar. Request with invalid property is causing compute api call failure.
Temporarily - Its works for me when I changed case from String iPProtocol to String IPProtocol.
@andreamlin - could you please take a look.
Hey @javabrown thanks a lot for the very very in-depth analysis of the problem! This has definitely made the bug much easier to fix. Looking into a solution.
@sirhamster thanks for the repro steps and the code snippet! I can repro this locally and am using the code snippet to iterate on :)
This fix should be out in the next google-cloud-compute release.
Update: this is now in master: https://github.com/googleapis/google-cloud-java/commit/f62e169b0fdb60a2cb1f427e6090f0496bfe8a50#diff-e2683f91996fb75cec15f1e56e0ae9ac and in the 0.78-alpha release.
Thanks again for all your help @sirhamster @javabrown !