Skip to content

Commit

Permalink
"Deploy" removed, Register Rework (#233)
Browse files Browse the repository at this point in the history
PR should not break anything, for old parts added a workarounds, that we
will remove in a month when all ExApps will publish their updates.

**Changes**:

* UI now use the same algorithm/code for ExApp `register` & `update` as
the CLI commands.
* Deprecated "deploy" command, now `register` commands performs deploy.

**Refactoring**:

* Removed internal `DispatchInit` command, as from CLI we already can do
it without spawning additional process.
* Removed hack(`status['active']`) when we have some half-enabled state
of ExApp when it is not enabled, but already can call APIs, now ExApp
enables before calling `/init`
* Made code more consistent in many place.

OTHER CHANGES FOR DEVS:

* For `--json-info` parameter in occ `register` command keys renamed:
"appid" -> "id", "system_app" -> "system"

_Old naming is still supported but will be removed in future, in such
way we make consistent parameters between `info.xml` and `--json-info`._

----

Related: #219 
_AppAPI will perform deploy & registration in a background and issue
should be fixed_

---------

Signed-off-by: Alexander Piskun <bigcat88@icloud.com>
Signed-off-by: Andrey Borysenko <andrey18106x@gmail.com>
Co-authored-by: Andrey Borysenko <andrey18106x@gmail.com>
  • Loading branch information
bigcat88 and andrey18106 authored Feb 19, 2024
1 parent b335a52 commit c7d1c3e
Show file tree
Hide file tree
Showing 33 changed files with 832 additions and 1,175 deletions.
12 changes: 0 additions & 12 deletions .github/workflows/tests-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@ jobs:
run: |
PHP_CLI_SERVER_WORKERS=2 php -S 127.0.0.1:8080 &
./occ app_api:daemon:register docker_local_sock Docker docker-install http /var/run/docker.sock http://127.0.0.1:8080/index.php
./occ app_api:app:deploy skeleton docker_local_sock \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/skeleton/appinfo/info.xml
./occ app_api:app:register skeleton docker_local_sock \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/skeleton/appinfo/info.xml
./occ app_api:app:enable skeleton
Expand Down Expand Up @@ -171,8 +169,6 @@ jobs:
docker_local_sock Docker docker-install http /var/run/docker.sock http://nextcloud/index.php \
--net=master_bridge
docker exec nextcloud sudo -u www-data php occ app_api:daemon:list
docker exec nextcloud sudo -u www-data php occ app_api:app:deploy skeleton docker_local_sock \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/skeleton/appinfo/info.xml
docker exec nextcloud sudo -u www-data php occ app_api:app:register skeleton docker_local_sock \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/skeleton/appinfo/info.xml
docker exec nextcloud sudo -u www-data php occ app_api:app:enable skeleton
Expand Down Expand Up @@ -252,8 +248,6 @@ jobs:
docker_by_port Docker docker-install http nextcloud-appapi-dsp:2375 http://nextcloud/index.php \
--net=master_bridge --haproxy_password=some_secure_password
docker exec nextcloud sudo -u www-data php occ app_api:daemon:list
docker exec nextcloud sudo -u www-data php occ app_api:app:deploy skeleton docker_by_port \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/skeleton/appinfo/info.xml
docker exec nextcloud sudo -u www-data php occ app_api:app:register skeleton docker_by_port \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/skeleton/appinfo/info.xml
docker exec nextcloud sudo -u www-data php occ app_api:app:enable skeleton
Expand Down Expand Up @@ -345,8 +339,6 @@ jobs:
docker_by_port Docker docker-install https host.docker.internal:2375 http://localhost:8080/index.php \
--net=host --haproxy_password=some_secure_password
docker exec nextcloud sudo -u www-data php occ app_api:daemon:list
docker exec nextcloud sudo -u www-data php occ app_api:app:deploy skeleton docker_by_port \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/skeleton/appinfo/info.xml
docker exec nextcloud sudo -u www-data php occ app_api:app:register skeleton docker_by_port \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/skeleton/appinfo/info.xml
docker exec nextcloud sudo -u www-data php occ app_api:app:enable skeleton
Expand Down Expand Up @@ -496,8 +488,6 @@ jobs:
PHP_CLI_SERVER_WORKERS=2 php -S 127.0.0.1:8080 &
./occ app_api:daemon:register docker_local_sock Docker docker-install http /var/run/docker.sock http://127.0.0.1:8080/index.php
./occ app_api:daemon:list
./occ app_api:app:deploy skeleton docker_local_sock \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/skeleton/appinfo/info.xml
./occ app_api:app:register skeleton docker_local_sock \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/skeleton/appinfo/info.xml
./occ app_api:app:enable skeleton
Expand Down Expand Up @@ -622,8 +612,6 @@ jobs:
docker_socket_local Docker docker-install http /var/run/docker.sock http://127.0.0.1:8080/index.php \
--net=host --set-default
./occ app_api:daemon:list
./occ app_api:app:deploy skeleton \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/skeleton/appinfo/info.xml
./occ app_api:app:register skeleton \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/skeleton/appinfo/info.xml
./occ app_api:app:enable skeleton
Expand Down
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
## [2.1.0 - 2024-02-19]

### Changed

- `deploy` command was deprecated, now `register` and `deploy` is one step. #233
- Installation of ExApps algorithm has been rewritten to provide a more comfortable experience. #233

### Fixed

- Translation provider API correctly supports "language detection" feature. #232

## [2.0.4 - 2024-02-08]

Expand Down
1 change: 0 additions & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ to join us in shaping a more versatile, stable, and secure app landscape.
<command>OCA\AppAPI\Command\ExApp\Deploy</command>
<command>OCA\AppAPI\Command\ExApp\Register</command>
<command>OCA\AppAPI\Command\ExApp\Unregister</command>
<command>OCA\AppAPI\Command\ExApp\DispatchInit</command>
<command>OCA\AppAPI\Command\ExApp\Update</command>
<command>OCA\AppAPI\Command\ExApp\Enable</command>
<command>OCA\AppAPI\Command\ExApp\Disable</command>
Expand Down
5 changes: 2 additions & 3 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@
['name' => 'ExAppsPage#enableApp', 'url' => '/apps/enable/{appId}', 'verb' => 'GET' , 'root' => ''],
['name' => 'ExAppsPage#enableApp', 'url' => '/apps/enable/{appId}', 'verb' => 'POST' , 'root' => ''],
['name' => 'ExAppsPage#getAppStatus', 'url' => '/apps/status/{appId}', 'verb' => 'GET' , 'root' => ''],
['name' => 'ExAppsPage#enableApps', 'url' => '/apps/enable', 'verb' => 'POST' , 'root' => ''],
['name' => 'ExAppsPage#disableApp', 'url' => '/apps/disable/{appId}', 'verb' => 'GET' , 'root' => ''],
['name' => 'ExAppsPage#disableApps', 'url' => '/apps/disable', 'verb' => 'POST' , 'root' => ''],
['name' => 'ExAppsPage#updateApp', 'url' => '/apps/update/{appId}', 'verb' => 'GET' , 'root' => ''],
['name' => 'ExAppsPage#uninstallApp', 'url' => '/apps/uninstall/{appId}', 'verb' => 'GET' , 'root' => ''],
['name' => 'ExAppsPage#viewApps', 'url' => '/apps/{category}', 'verb' => 'GET', 'defaults' => ['category' => ''] , 'root' => ''],
Expand All @@ -55,10 +53,11 @@
['name' => 'OCSApi#log', 'url' => '/api/v1/log', 'verb' => 'POST'],

['name' => 'OCSApi#getNCUsersList', 'url' => '/api/v1/users', 'verb' => 'GET'],
['name' => 'OCSApi#setAppProgress', 'url' => '/apps/status/{appId}', 'verb' => 'PUT'],
['name' => 'OCSApi#setAppInitProgress', 'url' => '/apps/status/{appId}', 'verb' => 'PUT'],

// ExApps
['name' => 'OCSExApp#getExAppsList', 'url' => '/api/v1/ex-app/{list}', 'verb' => 'GET'],
['name' => 'OCSExApp#getExApp', 'url' => '/api/v1/ex-app/info/{appId}', 'verb' => 'GET'],

// ExApps actions
['name' => 'OCSExApp#setExAppEnabled', 'url' => '/api/v1/ex-app/{appId}/enabled', 'verb' => 'PUT'],
Expand Down
7 changes: 3 additions & 4 deletions docs/DevSetup.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,15 @@ To see the complete list, execute ``make help``.
Docker remote API
*****************

The Docker Engine remote API can be easily configured via ``make dock2port`` and ``make dock-certs`` commands.
The first one will create a docker container to provide remote Docker Engine API.
The second one will configure generated certificates for created container with Docker remote API in Nextcloud.
The Docker Engine remote API can be easily configured via ``make dock2port`` command.
The command will create a docker container to provide remote Docker Engine API.

Afterward, register DaemonConfigs in Nextcloud using ``make dock-port`` command.

Docker by socket
****************

For Docker via socket, use the command ``make dock2sock``.
For Docker via socket, use the command ``make dock-sock``.
This registers DaemonConfigs in Nextcloud for the default socket connection (``/var/run/docker.sock``).

Make sure that socket has enough permissions for Nextcloud and webserver user to access it
Expand Down
39 changes: 10 additions & 29 deletions docs/ManagingExternalApplications.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,40 +12,21 @@ OCC CLI

There are several commands to work with ExApps:

1. Deploy
2. Register
3. Unregister
4. Update
5. Enable
6. Disable
7. List ExApps
8. List ExApp users
9. List ExApp scopes

Deploy
------

Command: ``app_api:app:deploy [--info-xml INFO-XML] [--] <appid> <daemon-config-name>``

The deploy command is the first ExApp installation step.

Arguments
*********

* ``appid`` - unique name of the ExApp (e.g. ``app_python_skeleton``, must be the same as in ``info.xml``)
* ``daemon-config-name`` - unique name of the daemon (e.g. ``docker_local_sock``)

Options
*******

* ``--info-xml INFO-XML`` **[required]** - path to info.xml file (url or local absolute path)
1. Register
2. Unregister
3. Update
4. Enable
5. Disable
6. List ExApps
7. List ExApp users
8. List ExApp scopes

Register
--------

Command: ``app_api:app:register [--force-scopes] [--info-xml INFO-XML] [--json-info JSON-INFO] [--] <appid> <daemon-config-name>``

The register command is the second ExApp installation step.
The register command is the first ExApp installation step.

Arguments
*********
Expand All @@ -58,7 +39,7 @@ Options

* ``--force-scopes`` *[optional]* - force scopes approval
* ``--json-info JSON-INFO`` **[optional]** - ExApp deploy JSON info (json string)
* ``--info-xml INFO-XML`` **[required]** - path to info.xml file (url or local absolute path)
* ``--info-xml INFO-XML`` **[optional]** - path to info.xml file (url or local absolute path)


Unregister
Expand Down
85 changes: 16 additions & 69 deletions docs/tech_details/Deployment.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ Deployment
Overview
--------

AppAPI ExApps deployment process in short consists of 3 steps:
AppAPI ExApps deployment process in short consists of 2 steps:

1. `DaemonConfig registration`_
2. `ExApp deployment`_
3. `ExApp registration`_
2. `ExApp registration`_

.. _occ_daemon_config_registration:

Expand Down Expand Up @@ -59,71 +58,48 @@ Example of ``occ`` **app_api:daemon:register** command:
sudo -u www-data php occ app_api:daemon:register docker_local_sock "My Local Docker" docker-install http /var/run/docker.sock "https://nextcloud.local" --net nextcloud
ExApp deployment
----------------
ExApp registration
------------------

Second step is to deploy ExApp on registered daemon.
This can be done by ``occ`` CLI command **app_api:app:deploy**:
Second and final step is to deploy and register ExApp in Nextcloud on previously registered daemon.
This can be done by ``occ`` CLI command **app_api:app:register**:

.. code-block:: bash
app_api:app:deploy <appid> <daemon-config-name> [--info-xml INFO-XML] [--]
.. note::
For development this step is skipped, as ExApp is deployed and started manually by developer.

.. warning::
After successful deployment (pull, create and start container), there is a heartbeat check with 90 seconds timeout (will be configurable).
app_api:app:register <appid> <daemon-config-name> [--force-scopes] [--]
Arguments
*********

* ``appid`` - unique name of the ExApp (e.g. ``app_python_skeleton``, must be the same as in ``info.xml``)
* ``appid`` - unique name of the ExApp (e.g. ``app_python_skeleton``, must be the same as in deployed container)
* ``daemon-config-name`` - unique name of the daemon (e.g. ``docker_local_sock``)

Options
*******

* ``--info-xml INFO-XML`` **[required]** - path to info.xml file (url or local absolute path)

Deploy result JSON
******************

Example of deploy result JSON:

.. code-block::
{
"appid": "app_python_skeleton",
"name":"App Python Skeleton",
"daemon_config_name": "local_docker_sock",
"version":"1.0.0",
"secret":"***generated-secret***",
"host":"app_python_skeleton",
"port":"9001",
"system_app": true
}
This JSON structure is used in ExApp registration step for development.
* ``--force-scopes`` **[optional]** - force scopes approval
* ``--info-xml INFO-XML`` **[optional]** - path to info.xml file with ExApp description (url or local absolute path)
* ``--json-info JSON-INFO`` **[optional]** - JSON with ExApp description

.. warning::
After successful deployment (pull, create and start container), there is a heartbeat check with 90 seconds timeout (will be configurable).

Manual install for development
******************************

For development purposes, you can install ExApp manually.
There is a ``manual-install`` DeployConfig type, which can be used in case of development.
For ExApp registration with it you need to provide JSON app info with structure described before
using **app_api:app:register** ``--json-info`` option.
For ExApp registration with it you need to provide JSON app info or a path to app XML file.

For all examples and applications we release we usually add manual_install command in it's makefile for easier development.

.. code-block::
php occ app_api:app:register nc_py_api manual_install --json-info \
"{\"appid\":\"nc_py_api\",\"name\":\"nc_py_api\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":$APP_PORT,\"scopes\":[\"SYSTEM\", \"FILES\", \"FILES_SHARING\", \"USER_INFO\", \"USER_STATUS\", \"NOTIFICATIONS\", \"WEATHER_STATUS\", \"TALK\"],\"system_app\":1}" \
"{\"id\":\"nc_py_api\",\"name\":\"nc_py_api\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":$APP_PORT,\"scopes\":[\"SYSTEM\", \"FILES\", \"FILES_SHARING\", \"USER_INFO\", \"USER_STATUS\", \"NOTIFICATIONS\", \"WEATHER_STATUS\", \"TALK\"],\"system\":1}" \
--force-scopes
.. note:: **Deployment/Startup of App should be done by developer when manual_install DeployConfig type is used.**
.. note:: **Deployment/Startup of App should be done by developer when ``manual-install`` DeployConfig type is used.**

Deploy env variables
********************
Expand All @@ -139,37 +115,8 @@ The following env variables are required and built automatically:
* ``APP_HOST`` - host ExApp is listening on
* ``APP_PORT`` - port ExApp is listening on (randomly selected by AppAPI)
* ``APP_PERSISTENT_STORAGE`` - path to mounted volume for persistent data storage between ExApp updates
* ``IS_SYSTEM_APP`` - ExApp system app flag (true|false)
* ``NEXTCLOUD_URL`` - Nextcloud URL to connect to

.. note::
Additional envs can be passed using multiple ``--env ENV_NAME=ENV_VAL`` options

ExApp registration
------------------

Final step is to register ExApp in Nextcloud.
This can be done by ``occ`` CLI command **app_api:app:register**:

.. code-block:: bash
app_api:app:register <appid> <daemon-config-name> [--force-scopes] [--]
Arguments
*********

* ``appid`` - unique name of the ExApp (e.g. ``app_python_skeleton``, must be the same as in deployed container)
* ``daemon-config-name`` - unique name of the daemon (e.g. ``docker_local_sock``)

Options
*******

* ``--force-scopes`` *[optional]* - force scopes approval
* ``--json-info JSON-INFO`` **[required]** - path to JSON file with deploy result (url or local absolute path)

With provided ``appid`` and ``daemon-config-name``, Nextcloud will retrieve ExApp info from deployed container and register it.
In case of ``manual-install`` DeployConfig type, ExApp info must be provided by ``--json-info`` option `as described before <#deploy-result-json-output>`_.

Application installation scheme
-------------------------------

Expand Down
2 changes: 1 addition & 1 deletion docs/tech_details/api/machinetranslation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Request data
"fr": "French",
},
"action_handler": "/handler_route_on_ex_app",
"action_detect_lang": "/detect_lang_fromt_text_handler",
"action_detect_lang": "/detect_lang_from_text_handler",
}
.. note::
Expand Down
24 changes: 13 additions & 11 deletions lib/BackgroundJob/ExAppInitStatusCheckJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ class ExAppInitStatusCheckJob extends TimedJob {
private const everyMinuteInterval = 60;

public function __construct(
ITimeFactory $time,
private ExAppMapper $mapper,
private AppAPIService $service,
private IConfig $config,
ITimeFactory $time,
private readonly ExAppMapper $mapper,
private readonly AppAPIService $service,
private readonly IConfig $config,
) {
parent::__construct($time);

Expand All @@ -34,13 +34,15 @@ protected function run($argument): void {
$initTimeoutMinutes = intval($this->config->getAppValue(Application::APP_ID, 'init_timeout', '40'));
foreach ($exApps as $exApp) {
$status = $exApp->getStatus();
if (!isset($status['init_start_time'])) {
continue;
}
if (time() >= ($status['init_start_time'] + $initTimeoutMinutes * 60)) {
$this->service->setAppInitProgress(
$exApp->getAppid(), 0, sprintf('ExApp %s initialization timed out (%sm)', $exApp->getAppid(), $initTimeoutMinutes * 60)
);
if (isset($status['init']) && $status['init'] !== 100) {
if (!isset($status['init_start_time'])) {
continue;
}
if (time() >= ($status['init_start_time'] + $initTimeoutMinutes * 60)) {
$this->service->setAppInitProgress(
$exApp, 0, sprintf('ExApp %s initialization timed out (%sm)', $exApp->getAppid(), $initTimeoutMinutes * 60)
);
}
}
}
} catch (Exception) {
Expand Down
Loading

0 comments on commit c7d1c3e

Please sign in to comment.