LCM Rules - Escape Variable Not Working Correctly
Rationale
Consider that a user wishes to create a K8s Custom Resouce where one paramenter should receive a JSON payload as a string. For example, this JSON payload, but as string:
[{"device": {"ipv4Address": {}, "networkAccessIdentifier": "123456789@domain.com", "phoneNumber": "+123456789"}, "provisioningId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "qosProfile": "QOS_A", "status": "AVAILABLE", "startedAt": "2024-12-12T09:52:26Z"}].
For this payload to be accepted by K8s Custom Resouce, OSL should pass the following value in the CR Spec:
"[{\"device\": {\"ipv4Address\": {}, \"networkAccessIdentifier\": \"123456789@domain.com\", \"phoneNumber\": \"+123456789\"}, \"provisioningId\": \"3fa85f64-5717-4562-b3fc-2c963f66afa6\", \"qosProfile\": \"QOS_A\", \"status\": \"AVAILABLE\", \"startedAt\": \"2024-12-12T09:52:26Z\"}]"
This represents an escaped version of Json payload. However, when using Blockly's escape
block, whenever there is a method block inside it, instead of escaping the value returned by the block inside, the escape
block escapes de literal block. Therefore, as the JSON Payload is not escaped properly, K8s interprets it as an array, leading to a failed deployment of the CR.
The issue in a nutshell
We have set up the following LCM rule to pass a JSON stringfied payload to the CR Spec. The rule is the following, and the value passed in the "Paramenter" Characteristic is "[{"device": {"ipv4Address": {}, "networkAccessIdentifier": "123456789@domain.com", "phoneNumber": "+123456789"}, "provisioningId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "qosProfile": "QOS_A", "status": "AVAILABLE", "startedAt": "2024-12-12T09:52:26Z"}]"
.
This rule resulted in the following error (in CRIDGE):
Caused by: io.fabric8.kubernetes.client.KubernetesClientException: Failure executing: POST at: https://10.255.32.238:6443/apis/example.com/v1/namespaces/9373738d-6181-4d64-837d-287799dd6a55/testresources. Message: TestResource.example.com "cr493533d5" is invalid: spec.parameter: Invalid value: "array": spec.parameter in body must be of type string: "array". Received status: Status(apiVersion=v1, code=422, details=StatusDetails(causes=[StatusCause(field=spec.parameter, message=Invalid value: "array": spec.parameter in body must be of type string: "array", reason=FieldValueTypeInvalid, additionalProperties={})], group=example.com, kind=TestResource, name=cr493533d5, retryAfterSeconds=null, uid=null, additionalProperties={}), kind=Status, message=TestResource.example.com "cr493533d5" is invalid: spec.parameter: Invalid value: "array": spec.parameter in body must be of type string: "array", metadata=ListMeta(_continue=null, remainingItemCount=null, resourceVersion=null, selfLink=null, additionalProperties={}), reason=Invalid, status=Failure, additionalProperties={}).
Therefore, Blockly's escape
block is not properly escaping whenever there is a method inside it.
Debugging Process
To properly understand why the escape
block is failing we have created a new LCM rule to escape a Service Characteristic and pass it to a CR Spec. The rule is the one below:
This rule resulted in the following Java Code:
logtext("Value of the Parameter Characteristic:");
logtext(getCharValAsString("Parameter"));
logtext("Escaped Parameter Characteristic:");
logtext("getCharValAsString(Parameter\"");
String parameterVar = getCurrentServicePropValue("serviceCharacteristicValue", "Parameter");
logtext("Computed parameterVar variable:");
logtext("$$XVALS_parameterVar_XVALE$$");
logtext("Escaped parameterVar variable:");
logtext("parameterVa");
logtext("Escaped parameterVar variable through compute variable:");
logtext("$$XVALS_parameterVar_XVALE$$");
logtext("Escaped original string passed via the Parameter Characteristic:");
logtext("[{\"device\": {\"ipv4Address\": {}, \"networkAccessIdentifier\": \"123456789@domain.com\", \"phoneNumber\": \"+123456789\"}, \"provisioningId\": \"3fa85f64-5717-4562-b3fc-2c963f66afa6\", \"qosProfile\": \"QOS_A\", \"status\": \"AVAILABLE\", \"startedAt\": \"2024-12-12T09:52:26Z\"}]");
{
java.util.HashMap<String,String> charvals = new java.util.HashMap<>();
charvals.put("_CR_SPEC",String.format("""
apiVersion: example.com/v1
kind: TestResource
metadata:
name: test-resource
spec:
parameter: %s
"""
, "getCharValAsString(Parameter\""));
setServiceRefCharacteristicsValues("Test-RFS", charvals);
}
This rule resulted in the following logs:
17:08:02.270 [task-14] INFO o.etsi.osl.osom.lcm.LcmBaseExecutor - From LCM Rule Log: Value of the Parameter Characteristic::
... From LCM Rule Log: [{"device": {"ipv4Address": {}, "networkAccessIdentifier": "123456789@domain.com", "phoneNumber": "+123456789"}, "provisioningId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "qosProfile": "QOS_A", "status": "AVAILABLE", "startedAt": "2024-12-12T09:52:26Z"}]
... From LCM Rule Log: Escaped Parameter Characteristic:
... From LCM Rule Log: getCharValAsString(Parameter"
... From LCM Rule Log: Computed parameterVar variable:
... From LCM Rule Log: null
... From LCM Rule Log: Escaped parameterVar variable:
... From LCM Rule Log: parameterVa
... From LCM Rule Log: Escaped parameterVar variable through compute variable:
... From LCM Rule Log: null
... From LCM Rule Log: Escaped original string passed via the Parameter Characteristic:
... From LCM Rule Log: [{"device": {"ipv4Address": {}, "networkAccessIdentifier": "123456789@domain.com", "phoneNumber": "+123456789"}, "provisioningId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "qosProfile": "QOS_A", "status": "AVAILABLE", "startedAt": "2024-12-12T09:52:26Z"}]
From looking at both the Java Code and the OSOM logs, we have noticed 2 issues:
- The Characteristic Value is not being properly escaped.
- The
Compute Variable
is also not working, as its result is anull
value. Additionally, when one uses this block, the name of the variable is passed as a string, instead of getting the actual value of the variable. Moreover, even the name of variable is not passed correclty. It seems blockly cuts the last character of the variable's name:logtext("Escaped parameterVar variable:"); logtext("parameterVa");