crim-ca / weaver

Weaver: Workflow Execution Management Service (EMS); Application, Deployment and Execution Service (ADES); OGC API - Processes; WPS; CWL Application Package
https://pavics-weaver.readthedocs.io
Apache License 2.0
24 stars 6 forks source link

Missing parameter value in workflow #358

Closed lhcorralo closed 2 years ago

lhcorralo commented 2 years ago

Greetings

First of all, congratulations for your great job. I have read the testbeds and used it, and it is an impressive piece of software.

Describe the bug

The execution of a workflow using WPS3 gives the error "ERROR [MainThread][PYWPS] Missing parameter value: input_files", being input_files the input parameter of the second step of the workflow.

How to Reproduce

  1. Prepare an hybrid configuration according to the description given in "context"

  2. Deploy the first step of the workflow, which runs the staging of several GeoTIFF

    {
    "processDescription": {
        "process": {
            "visibility": "public",
            "id": "Staging_S2L1C",
            "title": "Sentinel-2 L1C image staging",
            "abstract": "The test application to deploy docker image and display text",
            "version": "0.0.1"
        },
        "processVersion": "2.0"
    },
    "immediateDeployment": true,
    "executionUnit": [
        {
            "unit": {
                "cwlVersion": "v1.0",
                "class": "CommandLineTool",
                "baseCommand": [
                    "--output",
                    "output/",
                    "--api-endpoint",
                    "http://some-ip:5000/search"
                ],
                "requirements": {
                    "DockerRequirement": {
                        "dockerPull": "private.harbor.com/staging_s2l1c:latest"
                    }
                },
                "inputs": {
                    "start_time": {
                        "type": "string",
                        "inputBinding": {
                            "position": 1,
                            "prefix": "--start-time"
                        }
                    },
                    "end_time": {
                        "type": "string",
                        "inputBinding": {
                            "position": 2,
                            "prefix": "--end-time"
                        }
                    },
                    "aoi": {
                        "type": "string",
                        "inputBinding": {
                            "position": 3,
                            "prefix": "--aoi"
                        }
                    }
                },
                "outputs": {
                    "staging_output": {
                        "type": {
                            "type": "array",
                            "items": "File"
                        },
                        "outputBinding": {
                            "glob": "output/*.tif"
                        }
                    }
                }
            }
        }
    ],
    "deploymentProfileName": "http://www.opengis.net/profiles/eoc/dockerizedApplication"
    }
  3. Deploy the second step of the workflow, which analyzes the images looking for water extents.

    {
    "processDescription": {
        "process": {
            "visibility": "public",
            "id": "WaterExtent_S2",
            "title": "RME's Water Extent for Sentinel-2",
            "abstract": "It gets the water extent given a Sentinel-2 L1C image",
            "version": "0.0.1",
            "inputs": [
                {
                    "id": "input_files",
                    "title": "Input Sentinel-2 images",
                    "formats": [
                        {
                            "mimeType": "image/tiff",
                            "default": true
                        }
                    ],
                    "minOccurs": "1"
                }
            ],
            "outputs": [
                {
                    "id": "waterextentFiles",
                    "title": "Images with water mask",
                    "formats": [
                        {
                            "mimeType": "image/tiff",
                            "default": true
                        }
                    ]
                }
            ]
        },
        "processVersion": "2.0"
    },
    "immediateDeployment": true,
    "executionUnit": [
        {
            "unit": {
                "cwlVersion": "v1.0",
                "class": "CommandLineTool",
                "baseCommand": [
                    "-i",
                    "1",
                    "-o",
                    "output/"
                ],
                "requirements": {
                    "DockerRequirement": {
                        "dockerPull": "private.harbor.com/waterextent:0.2.0"
                    }
                },
                "inputs": {
                    "input_files": {
                        "type": {
                            "type": "array",
                            "items": "File"
                        },
                        "inputBinding": {
                            "position": 1
                        }
                    }
                },
                "outputs": {
                    "waterextentFiles": {
                        "type": {
                            "type": "array",
                            "items": "File"
                        },
                        "outputBinding": {
                            "glob": "output/*.tif"
                        }
                    }
                }
            }
        }
    ],
    "deploymentProfileName": "http://www.opengis.net/profiles/eoc/dockerizedApplication"
    }
  4. Deploy the workflow, which will pass the staged images to the water extent detector

    {
    "processDescription": {
        "process": {
            "visibility": "public",
            "id": "WorkflowWaterExtent",
            "title": "Workflow to test Water Extent for Sentinel-2",
            "abstract": "Workflow to save our beautiful necks",
            "version": "0.0.1"
        }
    },
    "executionUnit": [
        {
            "unit": {
                "cwlVersion": "v1.0",
                "class": "Workflow",
                "inputs": {
                    "start_time": "string",
                    "end_time": "string",
                    "aoi": "string"
                },
                "outputs": {
                    "output": {
                        "type": {
                            "type": "array",
                            "items": "File"
                        },
                        "outputSource": "water_extent/waterextentFiles"
                    }
                },
                "steps": {
                    "staging": {
                        "run": "Staging_S2L1C",
                        "in": {
                            "start_time": "start_time",
                            "end_time": "end_time",
                            "aoi": "aoi"
                        },
                        "out": [
                            "staging_output"
                        ]
                    },
                    "water_extent": {
                        "run": "WaterExtent_S2",
                        "in": {
                            "input_files": "staging/staging_output"
                        },
                        "out": [
                            "waterextentFiles"
                        ]
                    }
                }
            }
        }
    ],
    "deploymentProfileName": "http://www.opengis.net/profiles/eoc/workflow"
    }
  5. Execute the process WorkflowWaterExtent using the following arguments:

    {
    "mode": "async",
    "response": "document",
    "inputs": [
        {
            "id": "start_time",
            "data": "2021-07-14"
        },
        {
            "id": "end_time",
            "data": "2021-07-20"
        },
        {
            "id": "aoi",
            "data": "-0.3 39.8 0.1 40.1"
        }
    ],
    "outputs": [
        {
            "id": "output",
            "transmissionMode": "reference"
        }
    ]
    }

Expected behavior

The workflow should execute properly, returning a mask.

Other comments

Disclaimer

I know, as it is providedd, that the bug cannot be reproduced, as it uses images from private repositories. At the moment I cannot provide it as a easily reproducible example. However, I think the important part of the "bug" is in the process definitions, as the docker images are running properly in local CWL tests.

Exact error

The whole error is

gip-ems-worker  | [2021-11-10 10:55:15,343] INFO     [MainThread][weaver.processes.execution] 00:00:00   5% running    Following updates could take a while until the Application Package answers...
gip-ems-worker  | [2021-11-10 10:55:15,352] ERROR    [MainThread][PYWPS] Missing parameter value: input_files
gip-ems-worker  | [2021-11-10 10:55:15,352] ERROR    [MainThread][PYWPS] Exception: code: 400, description: input_files, locator: input_files
gip-ems-worker  | NoneType: None
gip-ems-worker  | [2021-11-10 10:55:15,352] ERROR    [MainThread][weaver.processes.execution] Failed running [Job <b4e8c6f1-552d-4e21-af06-9861d5846a33>]
gip-ems-worker  | Traceback (most recent call last):
gip-ems-worker  |   File "/opt/local/src/weaver/weaver/processes/execution.py", line 187, in execute_process
gip-ems-worker  |     mode=mode, job_uuid=job.id, remote_process=process, language=lang)
gip-ems-worker  |   File "/opt/local/src/weaver/weaver/wps/service.py", line 279, in execute_job
gip-ems-worker  |     wps_response = super(WorkerService, self).execute(worker_process_id, wps_request, job_uuid)
gip-ems-worker  |   File "/usr/local/lib/python3.7/site-packages/pywps/app/Service.py", line 82, in execute
gip-ems-worker  |     return self._parse_and_execute(process, wps_request, uuid)
gip-ems-worker  |   File "/usr/local/lib/python3.7/site-packages/pywps/app/Service.py", line 139, in _parse_and_execute
gip-ems-worker  |     inpt.identifier, inpt.identifier)
gip-ems-worker  | pywps.exceptions.MissingParameterValue: 400 MissingParameterValue: input_files
gip-ems-worker  | [2021-11-10 10:55:15,354] ERROR    [MainThread][weaver.processes.execution] 00:00:00  97% failed     Failed to run Job <b4e8c6f1-552d-4e21-af06-9861d5846a33>.
gip-ems-worker  | [2021-11-10 10:55:15,357] INFO     [MainThread][weaver.processes.execution] 00:00:00  98% dismissed  Job dismissed.
gip-ems-worker  | [2021-11-10 10:55:15,357] INFO     [MainThread][weaver.processes.execution] 00:00:00 100% dismissed  Job task complete.
gip-ems-worker  | [2021-11-10 10:55:15,360] INFO     [MainThread][celery.app.trace] Task weaver.processes.execution.execute_process[c72538fd-c1db-4ccb-9c5d-defe8c5081b1] succeeded in 0.16868097499991563s: 'dismissed'

That is, the parametetr failing is the input parameter for the second process of the workflow.

However, the wps:ProcessDescriptions for the process is returning

<wps:ProcessDescriptions
    xmlns:wps="http://www.opengis.net/wps/1.0.0"
    xmlns:ows="http://www.opengis.net/ows/1.1"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 ../wpsDescribeProcess_response.xsd" service="WPS" version="1.0.0" xml:lang="fr-CA">\n    
    <ProcessDescription wps:processVersion="0.0.1" storeSupported="true" statusSupported="true">\n        
        <ows:Identifier>WaterExtent_S2</ows:Identifier>\n        
        <ows:Title>RME\'s Water Extent for Sentinel-2</ows:Title>\n        
        <ows:Abstract>It gets the water extent given a Sentinel-2 L1C image</ows:Abstract>\n        
        <DataInputs>\n            
            <Input minOccurs="1" maxOccurs="9223372036854775807">\n                
                <ows:Identifier>input_files</ows:Identifier>\n                
                <ows:Title>Input Sentinel-2 images</ows:Title>\n                
                <ows:Abstract/>\n                
                <ComplexData maximumMegabytes="1">\n                    
                    <Default>\n                        
                        <Format>\n                            
                            <MimeType>image/tiff</MimeType>\n                        
                        </Format>\n                    
                    </Default>\n                    
                    <Supported>\n                        
                        <Format>\n                            
                            <MimeType>image/tiff</MimeType>\n                        
                        </Format>\n                    
                    </Supported>\n                
                </ComplexData>\n            
            </Input>\n        
        </DataInputs>\n        
        <ProcessOutputs>\n            
            <Output>\n                
                <ows:Identifier>waterextentFiles</ows:Identifier>\n                
                <ows:Title>Images with water mask</ows:Title>\n                
                <ows:Abstract/>\n                
                <ComplexOutput>\n                    
                    <Default>\n                        
                        <Format>\n                            
                            <MimeType>image/tiff</MimeType>\n                        
                        </Format>\n                    
                    </Default>\n                    
                    <Supported>\n                        
                        <Format>\n                            
                            <MimeType>image/tiff</MimeType>\n                        
                        </Format>\n                    
                    </Supported>\n                
                </ComplexOutput>\n            
            </Output>\n        
        </ProcessOutputs>\n    
    </ProcessDescription>\n
</wps:ProcessDescriptions>

which shows _inputfiles as input argument.

Step by step executions

The staging process works if not executed as a workflow, and also seems to be working within the workflow (see the log).

Other attempts

I also tried to use

"requirements": [
    {
        "class": "StepInputExpressionRequirement"
    }
 ]

As the whole workflow was working in version 3.5, but the process deployment gives me an error.

Note that I know that the water extent processor returns more than one file, but previous versions of Weaver discards files if more than one file is returned.

Context

Running as hybrid, with manager and worker both running version 4.2.1 from a docker-compose.yaml

The log is attached log.txt

github-actions[bot] commented 2 years ago

Thanks for submitting an issue. Make sure you have checked through existing/resolved issues to avoid duplicates. Also, make sure you provide enough details for us to be able to replicate and understand the problem.

fmigneault commented 2 years ago

@lhcorralo

Thank you for your interest in Weaver.

One thing I notice after deploying the first process is that the output seems to have the incorrect mediaType. Since none is provided explicitly, it defaults to text/plain. Auto-resolution of the media type from the glob patter output/*.tif is not yet supported (#24).

    "outputs": {
        "staging_output": {
            "title": "staging_output",
            "formats": [
                {
                    "default": true,
                    "mediaType": "text/plain"
                }
            ]
        }

I'm not sure if this can be the cause of the error connecting output of step 1 to input of step 2. Let me know if adding "mediaType": "image/tiff" resolves the problem.

I will investigate further in the meantime, but it will take me some time to work around the private docker images.

fmigneault commented 2 years ago

@lhcorralo

Follow-up on this issue.

I have identified that there is indeed an error introduced by this step: https://github.com/crim-ca/weaver/blob/6a7381edd03a5a597b7f2a5e27c8297c34f1ac6c/weaver/processes/wps3_process.py#L358-L364

A somewhat recent change to the format of results endpoint vs outputs endpoint makes it that the returned content is as follows:

{
  "staging_output": {
    "href": "http://localhost:4002/wpsoutputs/45c45987-8665-4caa-8af8-d90a06608879/gatineau_20170429.tif",
    "format": {
      "mediaType": "image/tiff"
    }
  }
}

Instead of the previous

{
  "outputs": {
    "staging_output": {
      "href": "http://localhost:4002/wpsoutputs/45c45987-8665-4caa-8af8-d90a06608879/gatineau_20170429.tif",
      "format": {
        "mediaType": "image/tiff"
      }
    }
  }
}

The fix will be out soon.

lhcorralo commented 2 years ago

@fmigneault thank you for your quick response!

Even having detected a bug, I think you are right in the rest of your comments, so:

  1. I will add the mimetype.
  2. I will try to generate two public docker images, one for running the staging, and other making some batch image processing. If there are more hidden bugs, it will help to debug them :)
fmigneault commented 2 years ago

@lhcorralo
I have been able to swap your docker images with some dummy operations/dockers that simply pass around a GeoTIF. Supposing your apps work, the fixes introduced in #360 should make the workflow work again. I have a few pending PRs to integrate before this one, but I will follow up with a new version soon. Let me know if you find any other issues.

lhcorralo commented 2 years ago

Those are great news! Thanks a lot :)

lhcorralo commented 2 years ago

Hi!

Just a small question... Is this bug fixed in release 4.3.0? I cannot find it in the changelog, but the dates match, so I am not very sure, sorry...

Thanks!

fmigneault commented 2 years ago

Hi. It is not in 4.3.0. It will be in 4.4.0 which I plan to release by the end of the day.

lhcorralo commented 2 years ago

Hi!

Bad news, I think the issue is still present :(

For easier debugging, I have uploaded https://github.com/lhcorralo/image-utils a simple project, where a docker image may be build. The code is almost trivial :)

The workflow is similar to the previous one:

  1. There is an application that generates the images
{
    "processDescription": {
        "process": {
            "visibility": "public",
            "id": "test_generation",
            "title": "Test image generation",
            "abstract": "Generates some test GeoTIFF",
            "version": "0.0.1",
            "outputs": [
                {
                    "id": "output_tifs",
                    "title": "GeoTIFF Images",
                    "formats": [
                        {
                            "default": true,
                            "mimeType": "image/tiff"
                        }
                    ]
                }
            ]
        },
        "processVersion": "2.0"
    },
    "immediateDeployment": true,
    "executionUnit": [
        {
            "unit": {
                "cwlVersion": "v1.0",
                "class": "CommandLineTool",
                "baseCommand": [
                    "generate",
                    "--output",
                    "output/"
                ],
                "requirements": {
                    "DockerRequirement": {
                        "dockerPull": "image_utils:latest"
                    }
                },
                "inputs": {
                    "base_name": {
                        "type": "string",
                        "inputBinding": {
                            "position": 1,
                            "prefix": "--base-name"
                        }
                    },
                    "count": {
                        "type": "int",
                        "inputBinding": {
                            "position": 2,
                            "prefix": "--count"
                        }
                    }
                },
                "outputs": {
                    "output_tifs": {
                        "type": {
                            "type": "array",
                            "items": "File"
                        },
                        "outputBinding": {
                            "glob": "output/*.tif"
                        }
                    }
                }
            }
        }
    ],
    "deploymentProfileName": "http://www.opengis.net/profiles/eoc/dockerizedApplication"
}
  1. There is an application that blurs the images.
{
    "processDescription": {
        "process": {
            "visibility": "public",
            "id": "test_blurring",
            "title": "Test image blurring",
            "abstract": "Test image blurring",
            "version": "0.0.1",
            "inputs": [
                {
                    "id": "input_files",
                    "title": "Input images",
                    "formats": [
                        {
                            "mimeType": "image/tiff",
                            "default": true
                        }
                    ],
                    "minOccurs": "1",
                    "maxOccurs": "unbounded"
                }
            ],
            "outputs": [
                {
                    "id": "output_tifs",
                    "title": "Blurred images",
                    "formats": [
                        {
                            "mimeType": "image/tiff",
                            "default": true
                        }
                    ]
                }
            ]
        },
        "processVersion": "2.0"
    },
    "immediateDeployment": true,
    "executionUnit": [
        {
            "unit": {
                "cwlVersion": "v1.0",
                "class": "CommandLineTool",
                "baseCommand": [
                    "-o",
                    "output/"
                ],
                "requirements": {
                    "DockerRequirement": {
                        "dockerPull": "image_utils:latest"
                    }
                },
                "inputs": {
                    "input_files": {
                        "type": {
                            "type": "array",
                            "items": "File"
                        },
                        "inputBinding": {
                            "position": 1,
                            "prefix": "--image"
                        }
                    }
                },
                "outputs": {
                    "output_tifs": {
                        "type": {
                            "type": "array",
                            "items": "File"
                        },
                        "outputBinding": {
                            "glob": "output/*.tif"
                        }
                    }
                }
            }
        }
    ],
    "deploymentProfileName": "http://www.opengis.net/profiles/eoc/dockerizedApplication"
}
  1. Register the workflow

    {
    "processDescription": {
        "process": {
            "visibility": "public",
            "id": "test_workflow",
            "title": "Workflow to test Weaver",
            "abstract": "Workflow to test Weaver",
            "version": "0.0.1"
        }
    },
    "executionUnit": [
        {
            "unit": {
                "cwlVersion": "v1.0",
                "class": "Workflow",
                "inputs": {
                    "base_name": "string",
                    "count": "int"
                },
                "outputs": {
                    "output": {
                        "type": {
                            "type": "array",
                            "items": "File"
                        },
                        "outputSource": "blurring/output_tifs"
                    }
                },
                "steps": {
                    "generation": {
                        "run": "test_generation",
                        "in": {
                            "base_name": "base_name",
                            "count": "count"
                        },
                        "out": [
                            "output_tifs"
                        ]
                    },
                    "blurring": {
                        "run": "test_blurring",
                        "in": {
                            "input_files": "generation/output_tifs"
                        },
                        "out": [
                            "output_tifs"
                        ]
                    }
                }
            }
        }
    ],
    "deploymentProfileName": "http://www.opengis.net/profiles/eoc/workflow"
    }
  2. Execute the workflow

    {
    "mode": "async",
    "response": "document",
    "inputs": [
        {
            "id": "base_name",
            "data": "castellon"
        },
        {
            "id": "count",
            "data": 4
        }
    ],
    "outputs": [
        {
            "id": "output",
            "transmissionMode": "reference"
        }
    ]
    }

Again, the workflow is failing with the following error:

gip-ems-worker  | [2021-11-23 21:38:07,374] INFO     [MainThread][weaver.processes.execution] 00:00:00   5% accepted   Following updates could take a while until the Application Package answers...
gip-ems-worker  | [2021-11-23 21:38:07,383] ERROR    [MainThread][PYWPS] Missing parameter value: input_files
gip-ems-worker  | [2021-11-23 21:38:07,383] ERROR    [MainThread][PYWPS] Exception: code: 400, description: input_files, locator: input_files
gip-ems-worker  | NoneType: None
gip-ems-worker  | [2021-11-23 21:38:07,383] ERROR    [MainThread][weaver.processes.execution] Failed running [Job <0f8d2d9f-2826-4bd3-8d10-c643bcda91d2>]
gip-ems-worker  | Traceback (most recent call last):
gip-ems-worker  |   File "/opt/local/src/weaver/weaver/processes/execution.py", line 165, in execute_process
gip-ems-worker  |     mode=mode, job_uuid=job.id, remote_process=process)
gip-ems-worker  |   File "/opt/local/src/weaver/weaver/wps/service.py", line 271, in execute_job
gip-ems-worker  |     wps_response = super(WorkerService, self).execute(worker_process_id, wps_request, job_uuid)
gip-ems-worker  |   File "/usr/local/lib/python3.7/site-packages/pywps/app/Service.py", line 79, in execute
gip-ems-worker  |     return self._parse_and_execute(process, wps_request, uuid)
gip-ems-worker  |   File "/usr/local/lib/python3.7/site-packages/pywps/app/Service.py", line 136, in _parse_and_execute
gip-ems-worker  |     inpt.identifier, inpt.identifier)
gip-ems-worker  | pywps.exceptions.MissingParameterValue: 400 MissingParameterValue: input_files

I have attached the weaver.log

Thank you!

Luis