From 88612ef1fddd8958acd19bd3e79a17cc36ac604b Mon Sep 17 00:00:00 2001 From: Neil Massey Date: Wed, 27 Nov 2024 11:47:13 +0000 Subject: [PATCH] Moved config templates to a single directory --- docs/manual/http_api.md | 122 ++++++++++++++++ docs/manual/making_a_xrd_key.md | 28 ++++ docs/manual/manual.md | 0 docs/manual/microservices/template.md | 26 ++++ docs/spec/uml/consumer_classes.png | Bin 0 -> 24208 bytes nlds/templates/server_config.j2 | 131 ------------------ nlds_processors/catalog/catalog_worker.py | 5 - nlds_processors/index.py | 4 +- nlds_processors/templates/processor_config.j2 | 18 --- .../templates/queues/archive_del_q.j2 | 15 -- .../templates/queues/archive_put_q.j2 | 19 --- nlds_processors/templates/queues/logging_q.j2 | 15 -- .../templates/queues/transfer_get_q.j2 | 19 --- .../templates/queues/transfer_put_q.j2 | 19 --- {test_run => nlds_utils}/nlds-up | 0 .../processors}/archive_get_q.j2 | 16 ++- server_config/processors/archive_put_q.j2 | 33 +++++ .../processors}/catalog_q.j2 | 23 ++- .../processors}/index_q.j2 | 13 +- server_config/processors/logging_q.j2 | 25 ++++ .../processors}/monitor_q.j2 | 15 +- .../processors}/nlds_q.j2 | 8 +- .../processors}/transfer_del_q.j2 | 10 +- server_config/processors/transfer_get_q.j2 | 32 +++++ server_config/processors/transfer_put_q.j2 | 32 +++++ server_config/server_config.j2 | 38 +++++ test_run/start_test_run.sh | 9 -- test_run/stop_test_run.sh | 3 - test_run/test_run.rc | 62 --------- 29 files changed, 416 insertions(+), 324 deletions(-) create mode 100644 docs/manual/http_api.md create mode 100644 docs/manual/making_a_xrd_key.md create mode 100644 docs/manual/manual.md create mode 100644 docs/manual/microservices/template.md create mode 100644 docs/spec/uml/consumer_classes.png delete mode 100644 nlds/templates/server_config.j2 delete mode 100644 nlds_processors/templates/processor_config.j2 delete mode 100644 nlds_processors/templates/queues/archive_del_q.j2 delete mode 100644 nlds_processors/templates/queues/archive_put_q.j2 delete mode 100644 nlds_processors/templates/queues/logging_q.j2 delete mode 100644 nlds_processors/templates/queues/transfer_get_q.j2 delete mode 100644 nlds_processors/templates/queues/transfer_put_q.j2 rename {test_run => nlds_utils}/nlds-up (100%) rename {nlds_processors/templates/queues => server_config/processors}/archive_get_q.j2 (59%) create mode 100644 server_config/processors/archive_put_q.j2 rename {nlds_processors/templates/queues => server_config/processors}/catalog_q.j2 (65%) rename {nlds_processors/templates/queues => server_config/processors}/index_q.j2 (51%) create mode 100644 server_config/processors/logging_q.j2 rename {nlds_processors/templates/queues => server_config/processors}/monitor_q.j2 (57%) rename {nlds_processors/templates/queues => server_config/processors}/nlds_q.j2 (83%) rename {nlds_processors/templates/queues => server_config/processors}/transfer_del_q.j2 (59%) create mode 100644 server_config/processors/transfer_get_q.j2 create mode 100644 server_config/processors/transfer_put_q.j2 create mode 100644 server_config/server_config.j2 delete mode 100755 test_run/start_test_run.sh delete mode 100755 test_run/stop_test_run.sh delete mode 100644 test_run/test_run.rc diff --git a/docs/manual/http_api.md b/docs/manual/http_api.md new file mode 100644 index 00000000..89fdc1fb --- /dev/null +++ b/docs/manual/http_api.md @@ -0,0 +1,122 @@ +HTTP API +======== + +This section covers the HTTP API used to interact with the Near-Line Data +Store (NLDS), and the HTTP messages that must be sent to the API to carry out +tasks with the NLDS. It is divided upon task type: + +* [PUT / PUTLIST command](#put-command) +* [PUTLIST command](#putlist-command) +* [GET command](#get-command) +* [GETLIST command](#getlist-command) +* [DEL command](#del-command) +* [DELLIST command](#dellist-command) + +### PUT / PUTLIST command + +The `PUT` and `PUTLIST` commands have been combined into a single HTTP API function, as transferring +a single file is just the same as transferring a list of files - except there is only one filepath +in the list. Therefore, the filepath(s) are specified in the body of the HTTP message, and the other +parameters, some of which are optional, are specified in the header / input parameter part of the message. +Any optional metadata parameters, such as the holding label, id or tags are also specified in the body. + +| API endpoint | /files | +|---|---| +| HTTP method | PUT | +| Parameters | transaction_id: `UUID` | +| | token: `str` (OAuth2 token) | +| | user: `str` | +| | group: `str` | +| | tenancy: `str` (Optional) | +| | job_label: `str` (Optional) | +| | access_key: `str` | +| | secret_key: `str` | +| Body | *JSON*: `Dict {"filelist" : List, "label": str, "tag": Dict, "holding_id": int}` | +| Example | `/files/put?transaction_id=1;user="bob";group="root"` | +| Body example | `{"filelist" : ["file1", "file2", "file3"]}`| + + +### GET command + +The `GET` command is no longer used by the NLDS client, but it is left in the HTTP API in case +another application wishes to use a very simple GET function. All of the parameters, some of which +are optional, are specified in the header / input parameters. This method does not support the +full features of specifying a holding label, or id, or tags, as the `GET` HTTP method does not support +a body. + +| API endpoint | /files | +|---|---| +| HTTP method | GET | +| Parameters | transaction_id: `UUID` | +| | token: `str` (OAuth2 token) | +| | user: `str` | +| | group: `str` | +| | filepath: `str` | +| | target: `str` (Optional) | +| | tenancy: `str` (Optional) | +| | job_label: `str` (Optional) | +| | access_key: `str` | +| | secret_key: `str` | +| Body | none | +| Example | `GET /files/transaction_id=1;user="bob";group="root";filepath="myfile.txt"` | + +### GETLIST command + +The `GETLIST` command is used to get a list of files from the NLDS. Of course, this list could have +only a single file in it, meaning that the functionality overlaps with the `GET` command somewhat. +The `GETLIST` uses the HTTP PUT method (rather than GET) so that a body can be supplied with the +HTTP message. It supports the full features of specifying a label, id or tags. + +| API endpoint | /files/getlist | +|---|---| +| HTTP method | PUT | +| Parameters | transaction_id: `UUID` | +| | token: `str` (OAuth2 token) | +| | user: `str` | +| | group: `str` | +| | tenancy: `str` (Optional) | +| | target: `str` (Optional) | +| | job_label: `str` (Optional) | +| | access_key: `str` | +| | secret_key: `str` | +| Body | *JSON* `Dict {"filelist" : List, "label": str, "tag": Dict, "holding_id": int}`| +| Example | `/files/getlist?transaction_id=1;user="bob";group="root";`| +| Body example | `{"filelist" : ["file1", "file2", "file3"]}`| + + + +### DEL / DELLIST command + +Like the `PUT` / `PUTLIST` command, the `DEL` / `DELLIST` commands are combined into a single HTTP +PUT method. This is because deleting a single file is the same as deleting a list of files, just +with a single file. Like the `PUT` / `PUTLIST` command, the filelist is specified in the body, +along with the metadata commands, with the input parameters / header passing the transaction id, +user, group, etc. + +| API endpoint | /files/dellist | +|---|---| +| HTTP method | PUT | +| Parameters | transaction_id: `UUID` | +| | token: `str` (OAuth2 token) | +| | user: `str` | +| | group: `str` | +| | tenancy: `str` (Optional) | +| | job_label: `str` (Optional) | +| | access_key: `str` | +| | secret_key: `str` | +| Body | *JSON* `Dict {"filelist" : List, "label": str, "tag": Dict, "holding_id": int}`| +| Example | `/files/dellist?transaction_id=1;user="bob";group="root"`| +| Body example | `{"filelist" : ["file1", "file2", "file3"]}`| \ No newline at end of file diff --git a/docs/manual/making_a_xrd_key.md b/docs/manual/making_a_xrd_key.md new file mode 100644 index 00000000..e01d3361 --- /dev/null +++ b/docs/manual/making_a_xrd_key.md @@ -0,0 +1,28 @@ +Making a XrootD key +=================== + +To read or write files to antares tape via XrootD, a key needs to be generated +and then passed to `xrdfs`, `xrdcp` or the Python libraries via two +environment variables. + +The key can be found in the `nlds-consumer-deploy` repository, in the +`conf/archive_put/staging_secrets.yaml` file (amongst others). It is the +`tapeSecretSettings` Value. + +Once you have this secret, create the keytab file from it and change the +permissions (xrdfs will not let you use the key in any other state): + + echo "key string from repo" > ~/.nlds-xrd.keytab + chmod g-r,o-r ~/.nlds-xrd.keytab + +This will allow the user to use `xrdfs` and `xrdcp`. To allow the nlds to use +tke key copy it to `/etc/nlds` and change ownership and permissions + + sudo cp ~/.nlds-xrd.keytab /etc/nlds/nlds-xrd.keytab + sudo chown root /etc/nlds/nlds-xrd.keytab + sudo chmod g-r,o-r /etc/nlds/nlds-xrd.keytab + +Then set these environment variables: + + export XrdSecPROTOCOL=sss + export XrdSecSSSKT=~/.nlds-xrd.keytab \ No newline at end of file diff --git a/docs/manual/manual.md b/docs/manual/manual.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/manual/microservices/template.md b/docs/manual/microservices/template.md new file mode 100644 index 00000000..d20dcf04 --- /dev/null +++ b/docs/manual/microservices/template.md @@ -0,0 +1,26 @@ +Microservices template +====================== + +Message input +------------- + +| routing key | message contents | +|-------------|------------------| + +Message mapping +--------------- + +| input key | output key | +|-----------|------------| + +Message output +-------------- + +| routing key | message contents | +|-------------|------------------| + +Process +------- + +| api action | function | +|------------|----------| \ No newline at end of file diff --git a/docs/spec/uml/consumer_classes.png b/docs/spec/uml/consumer_classes.png new file mode 100644 index 0000000000000000000000000000000000000000..4e618da9a50e85c9b7d4810abf5f2e41dfcaf4aa GIT binary patch literal 24208 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 KCKZP