Skip to content

Commit e2e16f4

Browse files
committed
Release 5.13.8
2 parents e18a55d + 1597ed7 commit e2e16f4

File tree

17 files changed

+265
-46
lines changed

17 files changed

+265
-46
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ endif()
2424

2525
find_package( ecbuild 3.4 REQUIRED HINTS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../ecbuild /workspace/ecbuild) # Before project()
2626

27-
project( ecflow LANGUAGES CXX VERSION 5.13.7 )
27+
project( ecflow LANGUAGES CXX VERSION 5.13.8 )
2828

2929
# Important: the project version is used, as generated CMake variables, to filter .../ecflow/core/ecflow_version.h.in
3030

docs/conf.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@
9393

9494

9595
def get_ecflow_version():
96-
version = "5.13.7"
96+
version = "5.13.8"
9797
ecflow_version = version.split(".")
9898
print("Extracted ecflow version '" + str(ecflow_version))
9999
return ecflow_version

docs/glossary.rst

+11-1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@
6666
- :code:`polling`, the value (in seconds) used to periodically contact the Aviso server
6767
- :code:`auth`, the location to the Aviso authentication credentials file
6868

69+
.. note::
70+
71+
The `listener` parameter is expected to be a valid single line JSON string, enclosed in single quotes.
72+
6973
The value of the properties :code:`url`, :code:`schema`, :code:`polling`,
7074
and :code:`auth` can be composed of :term:`Variables<variable>`. When
7175
these properties are not provided, the following default values are used:
@@ -92,7 +96,9 @@
9296
can be reloaded (without unqueuing the Task) by issuing an Alter change command with
9397
the value :code:`reload` to the relevant Aviso attribute.
9498

95-
The authentication credentials file is expected to be in JSON format, following the `ECMWF Web API <https://www.ecmwf.int/en/computing/software/ecmwf-web-api>`_:
99+
The authentication credentials file is expected to be in JSON format, following
100+
the `ECMWF Web API <https://www.ecmwf.int/en/computing/software/ecmwf-web-api>`_
101+
(this is conventionally stored in a file located at `$HOME/.ecmwfapirc`):
96102

97103
.. code-block:: json
98104
@@ -104,6 +110,10 @@
104110
105111
Only the fields :code:`url`, :code:`key`, and :code:`email` are required; any additional fields are ignored.
106112

113+
The Aviso schema file is a JSON file that defines the event listener schema. This is used by both Aviso server
114+
and client (thus, by ecFlow) to define the valid event types and request parameters used when polling for
115+
notifications. The schema file path must be provided to the `schema` option (or via the `ECF_AVISO_SCHEMA` variable).
116+
107117
check point
108118
The check point file is like the :term:`suite definition`, but includes all the state information.
109119

docs/python_api/AvisoAttr.rst

+21-6
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,41 @@ An :term:`aviso` attribute, assigned to a :term:`node`, represents an external t
1212
Although :term:`aviso` attributes can be set at any level (Suite, Family, Task), it only makes sense to assign aviso attributes to tasks, and only one aviso attribute per node is allowed.
1313

1414

15-
Constructor::
16-
17-
AvisoAttr(name, listener, ...)
15+
Constructors::
16+
17+
AvisoAttr(name, listener) (1)
18+
AvisoAttr(name, listener, url)
19+
AvisoAttr(name, listener, url, schema)
20+
AvisoAttr(name, listener, url, schema, polling)
21+
AvisoAttr(name, listener, url, schema, polling, auth)
22+
with:
1823
string name: The Aviso attribute name
1924
string listener: The Aviso listener configuration (in JSON format)
2025
string url: The URL used to contact the Aviso server
2126
string schema: The path to the Aviso schema
2227
string polling: The polling interval used to contact the Aviso server
2328
string auth: The path to the Aviso Authentication credentials
2429

30+
Note: Default values, based on %ECF_AVISO_...% variables, will be used for the calls where
31+
the parameters url, schema, polling, and auth are not provided
32+
33+
We suggest to specify :code:`%ECF_AVISO_***%` variables once (at suite level), and then create the
34+
Aviso attributes passing just the name and the listener definition as per call `(1)`.
35+
36+
.. note:: The `listener` parameter is expected to be a valid single line JSON string, enclosed in single quotes.
37+
As a convenience, missing surrounding single quotes are detected and will automatically be added.
38+
39+
Details regarding the format of `listener` are in the section describing the :term:`aviso` attribute.
40+
2541

2642
Usage:
2743

2844
.. code-block:: python
2945
30-
t1 = Task('t1',
31-
AvisoAttr('name', '{...}', 'http://aviso.com', '60', '/path/to/auth'))
46+
t1 = Task('t1', AvisoAttr('name', "'{...}'"))
3247
3348
t2 = Task('t2')
34-
t2.add_aviso('name', '{...}', 'http://aviso.com', '60', '/path/to/auth')
49+
t2.add_aviso('name', "'{...}'", 'http://aviso.com', '60', '/path/to/auth')
3550
3651
The parameters `url`, `schema`, `polling`, and `auth` are optional
3752

docs/release_notes/version_5.13.rst

+20
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,26 @@ Version 5.13 updates
66
.. role:: jiraissue
77
:class: hidden
88

9+
Version 5.13.8
10+
==============
11+
12+
* `Released <https://confluence.ecmwf.int/display/ECFLOW/Releases>`__\ on 2025-03-12
13+
14+
General
15+
-------
16+
17+
- **Fix** correct Aviso notification retrieval after automatic requeueing :jiraissue:`ECFLOW-2010`
18+
19+
Python
20+
------
21+
22+
- **Fix** correct quote handling for ecflow.AvisoAttr listener :jiraissue:`ECFLOW-2011`
23+
24+
Documentation
25+
-------------
26+
27+
- **Improvement** clarify use of schema for ecFlow Aviso attribute :jiraissue:`ECFLOW-2008`
28+
- **Improvement** clarify how to define ecFlow Aviso authentication :jiraissue:`ECFLOW-2008`
929

1030
Version 5.13.7
1131
==============

docs/ug/cookbook/how_to_trigger_a_task_based_on_aviso_notification.rst

+22
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,28 @@ Follow the recommended practice of defining ecFlow :term:`variables<variable>` a
5353
endfamily
5454
endsuite
5555
56+
To enable Aviso authentication, set the `--auth` option (directly or via the `ECF_AVISO_AUTH`
57+
variable) to the path of the JSON file containing the authentication credentials, which follows the
58+
`ECMWF Web API <https://www.ecmwf.int/en/computing/software/ecmwf-web-api>`_. The credentials file
59+
is conventionally located at `$HOME/.ecmwfapirc`, with the following content:
60+
61+
.. code-block:: json
62+
63+
{
64+
"url" : "https://api.ecmwf.int/v1",
65+
"key" : "<your-api-key>",
66+
"email" : "<your-email>"
67+
}
68+
69+
The Aviso schema file is a JSON file that defines the event listener schema. This is used by
70+
both Aviso server and client (thus, by ecFlow) to define the valid event types and request
71+
parameters used when polling for notifications. The schema file path must be provided to the
72+
`--schema` option (or via the `ECF_AVISO_SCHEMA` variable).
73+
74+
The Aviso schema, `event_listener_schema.json`, used by ECMWF is available at `<https://github.com/ecmwf/aviso-deployment/tree/main/schema>`_,
75+
and is specific to the Aviso server being used (access is currently restricted; if necessary, please contact
76+
support to request the files).
77+
5678
Define a Suite with an `Aviso` dependent Task
5779
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5880

docs/ug/user_manual/text_based_suite_definition/external/aviso.rst

+16-6
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@ notification. The options defining the attribute can be provided in any order.
1919
# --auth %ECF_AVISO_AUTH%
2020
# --polling %ECF_AVISO_POLLING%
2121
22-
Notice that the :code:`--listener` option must be surrounded by single quotes,
23-
and is composed as a single line `JSON`. The `JSON` must define two fields:
22+
.. note::
23+
24+
The `listener` parameter is expected to be a valid single line JSON string, enclosed in single quotes.
25+
26+
The listener must define two fields (as per the `Aviso Listerner <https://pyaviso.readthedocs.io/en/latest/guide/define_my_listener.html>`_ definition):
2427

2528
- :code:`event`, specifies the type of Aviso event
2629
- :code:`request`, specifies a dictionary with the parameters used to check for matches of Aviso notifications
@@ -34,12 +37,19 @@ The following are some examples:
3437
'{ "event": "mars", "request": { "class": "od", "expver": "0001", "domain": "g", "stream": "abcd", "step": 0 } }'
3538
3639
The Authentication credentials, provided via option :code:`--auth`, are
37-
provided in a `JSON` file with the following content:
40+
provided in a `JSON` file with the content following the
41+
`ECMWF Web API <https://www.ecmwf.int/en/computing/software/ecmwf-web-api>`_
42+
(this is conventionally stored in a file located at `$HOME/.ecmwfapirc`):
3843

3944
.. code-block:: json
4045
4146
{
42-
"url": "http://host.int:1234",
43-
"key": "*******************************************************************",
44-
"email": "[email protected]"
47+
"url" : "https://api.ecmwf.int/v1",
48+
"key" : "<your-api-key>",
49+
"email" : "<your-email>"
4550
}
51+
52+
The Aviso schema file is a JSON file that defines the event listener schema. This is used by
53+
both Aviso server and client (thus, by ecFlow) to define the valid event types and request
54+
parameters used when polling for notifications. The schema file path must be provided to the
55+
`--schema` option (or via the `ECF_AVISO_SCHEMA` variable).

libs/attribute/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ set(test_srcs
1212
# Sources
1313
test/TestAttributes_main.cpp
1414
test/TestAttrSerialization.cpp
15+
test/TestAvisoAttr.cpp
1516
test/TestCron.cpp
1617
test/TestDateAttr.cpp
1718
test/TestDayAttr.cpp

libs/attribute/test/TestAvisoAttr.cpp

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2009- ECMWF.
3+
*
4+
* This software is licensed under the terms of the Apache Licence version 2.0
5+
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6+
* In applying this licence, ECMWF does not waive the privileges and immunities
7+
* granted to it by virtue of its status as an intergovernmental organisation
8+
* nor does it submit to any jurisdiction.
9+
*/
10+
11+
#include <string>
12+
13+
#include <boost/test/unit_test.hpp>
14+
15+
#include "ecflow/node/AvisoAttr.hpp"
16+
17+
BOOST_AUTO_TEST_SUITE(U_Attributes)
18+
19+
BOOST_AUTO_TEST_SUITE(T_AvisoAttr)
20+
21+
BOOST_AUTO_TEST_CASE(can_create_aviso_attribute_with_all_parameters) {
22+
23+
using namespace ecf;
24+
25+
auto aviso = AvisoAttr{nullptr,
26+
"A",
27+
R"({ "event": "mars", "request": { "class": "od"} })",
28+
"http://host:port",
29+
"/path/to/schema",
30+
"60",
31+
0,
32+
"/path/to/auth",
33+
"'this is a reason'"};
34+
35+
BOOST_CHECK_EQUAL(aviso.name(), "A");
36+
BOOST_CHECK_EQUAL(aviso.listener(), R"('{ "event": "mars", "request": { "class": "od"} }')");
37+
BOOST_CHECK_EQUAL(aviso.url(), "http://host:port");
38+
BOOST_CHECK_EQUAL(aviso.schema(), "/path/to/schema");
39+
BOOST_CHECK_EQUAL(aviso.auth(), "/path/to/auth");
40+
BOOST_CHECK_EQUAL(aviso.polling(), "60");
41+
BOOST_CHECK_EQUAL(aviso.reason(), "'this is a reason'");
42+
}
43+
44+
BOOST_AUTO_TEST_CASE(can_create_aviso_attribute_ensuring_single_quotes_when_absent) {
45+
46+
using namespace ecf;
47+
48+
// Notice the absence of single quotes, on both the listener and reason
49+
auto aviso = AvisoAttr{nullptr,
50+
"A",
51+
R"({ "event": "mars", "request": { "class": "od"} })",
52+
"http://host:port",
53+
"/path/to/schema",
54+
"60",
55+
0,
56+
"/path/to/auth",
57+
"this is a reason"};
58+
59+
BOOST_CHECK_EQUAL(aviso.name(), "A");
60+
BOOST_CHECK_EQUAL(aviso.listener(), R"('{ "event": "mars", "request": { "class": "od"} }')");
61+
BOOST_CHECK_EQUAL(aviso.url(), "http://host:port");
62+
BOOST_CHECK_EQUAL(aviso.schema(), "/path/to/schema");
63+
BOOST_CHECK_EQUAL(aviso.auth(), "/path/to/auth");
64+
BOOST_CHECK_EQUAL(aviso.polling(), "60");
65+
BOOST_CHECK_EQUAL(aviso.reason(), "'this is a reason'");
66+
}
67+
68+
BOOST_AUTO_TEST_SUITE_END()
69+
70+
BOOST_AUTO_TEST_SUITE_END()

libs/node/src/ecflow/node/AvisoAttr.cpp

+24-6
Original file line numberDiff line numberDiff line change
@@ -21,28 +21,42 @@
2121

2222
namespace ecf {
2323

24+
namespace implementation {
25+
26+
std::string ensure_single_quotes(const AvisoAttr::listener_t listener) {
27+
using namespace std::string_literals;
28+
if (!listener.empty() && listener.front() == '\'' && listener.back() == '\'') {
29+
return listener;
30+
}
31+
else {
32+
return "'"s + listener + "'"s;
33+
}
34+
}
35+
36+
} // namespace implementation
37+
2438
bool AvisoAttr::is_valid_name(const std::string& name) {
2539
return ecf::Str::valid_name(name);
2640
}
2741

2842
AvisoAttr::AvisoAttr(Node* parent,
2943
name_t name,
30-
listener_t listener,
44+
const listener_t& listener,
3145
url_t url,
3246
schema_t schema,
3347
polling_t polling,
3448
revision_t revision,
3549
auth_t auth,
36-
reason_t reason)
50+
const reason_t& reason)
3751
: parent_{parent},
3852
parent_path_{parent ? parent->absNodePath() : ""},
3953
name_{std::move(name)},
40-
listener_{std::move(listener)},
54+
listener_{implementation::ensure_single_quotes(listener)},
4155
url_{std::move(url)},
4256
schema_{std::move(schema)},
4357
polling_{std::move(polling)},
4458
auth_{std::move(auth)},
45-
reason_{std::move(reason)},
59+
reason_{implementation::ensure_single_quotes(reason)},
4660
revision_{revision},
4761
controller_{nullptr} {
4862
if (!ecf::Str::valid_name(name_)) {
@@ -112,7 +126,9 @@ bool AvisoAttr::isFree() const {
112126

113127
if (notifications.empty()) {
114128
// No notifications, nothing to do -- task continues to wait
115-
SLOG(D, "AvisoAttr: (path: " << this->path() << ", name: " << name_ << ", listener: " << listener_ << "): no notifications found");
129+
SLOG(D,
130+
"AvisoAttr: (path: " << this->path() << ", name: " << name_ << ", listener: " << listener_
131+
<< "): no notifications found");
116132
return false;
117133
}
118134

@@ -151,7 +167,9 @@ bool AvisoAttr::isFree() const {
151167

152168
ecf::visit_parents(*parent_, [n = this->state_change_no_](Node& node) { node.set_state_change_no(n); });
153169

154-
SLOG(D, "AvisoAttr: (path: " << this->path() << ", name: " << name_ << ", listener: " << listener_ << ") " << std::string{(is_free ? "" : "no ")} + "notifications found");
170+
SLOG(D,
171+
"AvisoAttr: (path: " << this->path() << ", name: " << name_ << ", listener: " << listener_ << ") "
172+
<< std::string{(is_free ? "" : "no ")} + "notifications found");
155173

156174
return is_free;
157175
}

libs/node/src/ecflow/node/AvisoAttr.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,13 @@ class AvisoAttr {
6969
AvisoAttr() = default;
7070
AvisoAttr(Node* parent,
7171
name_t name,
72-
listener_t handle,
72+
const listener_t& handle,
7373
url_t url,
7474
schema_t schema,
7575
polling_t polling,
7676
revision_t revision,
7777
auth_t auth,
78-
reason_t reason);
78+
const reason_t& reason);
7979
AvisoAttr(const AvisoAttr& rhs) = default;
8080

8181
AvisoAttr& operator=(const AvisoAttr& rhs) = default;

0 commit comments

Comments
 (0)