diff --git a/specs/ocata/approved/environment-edit.rst b/specs/ocata/approved/environment-edit.rst new file mode 100644 index 0000000..10847a1 --- /dev/null +++ b/specs/ocata/approved/environment-edit.rst @@ -0,0 +1,363 @@ +.. + This work is licensed under a Creative Commons Attribution 3.0 Unported + License. + + http://creativecommons.org/licenses/by/3.0/legalcode + +================================================== +Capability to edit existing environment properties +================================================== + +https://blueprints.launchpad.net/murano/+spec/environment-edit + +The spec proposes mechanism for users to edit any details of an existing +environment, for example edit its regions, set home region, change the +networks or any other possible input field. + +Problem description +=================== + +Current Murano API and python-muranoclient only allow to specify its home +region and default network during the environment creation. These parameters +cannot be seen and cannot be updated by the user after the environment +creation. Users may want to examine and change these or other environment +properties after it is created. Adding a mechanism to apply custom JSON-patch +to environment object model would provide this capability and add a great +flexibility in managing environments. + + +Proposed change +=============== + +Changes in API +-------------- + +It is proposed to create a new API endpoint +`/environments//model` and two calls to it using GET and PATCH +requests. + +**GET** request provides environment object model where all environment +properties can be seen. See the `REST API impact` section for the example of +such output. If session is specified in the request and it is not in deploying +state, response gives modified environment model from the session, otherwise +actual environment model. + +**PATCH** request allows to perform custom change to the environment object +model using JSON-patch object. It requires session to be specified by request +and saves changes to environment model in the specified session. + +JSON-patch is a valid JSON that contains a list of changes to be applied to +the current object. Each change contains a dictionary with three keys: ``op``, +``path`` and ``value``. ``op`` (operation) can be one of the three values: +`add`, `replace` or remove`. *See RFC 6902 [1] for details*. + +To indicate that body of the request is JSON-patch and validate correct +format of the body, a new media type should be added - +`application/env-model-json-patch`. During the validation in the middleware, +the following conditions must be checked against the passed object: + +* It is a valid JSON-patch object (already implemented for + `application/murano-packages-json-patch` media type and should be reused). + Otherwise `400 Bad Request` response is given. + +* Not all kinds of operations can be applied to all sections of the + environment model. The list of allowed operations is the following: + + + defaultNetworks: replace + + name: replace + + region: replace + + regions: add, replace, remove + + services: add, replace, remove + + ?: add, replace, remove + + Attempt to perform the restricted change will result in the `403 Forbidden` + response. + +* Types of the environment properties and possible values are validated by the + appropriate JSON-schema. Otherwise `400 Bad Request` response is given. + +Changes in python-muranoclient +------------------------------ + +To support the new API calls, corresponding python-muranoclient methods for +environments are needed: ``get_model`` and ``update_model`` respectively. + +New CLI command that displays the result of ``get_model`` method: + +.. code-block:: shell + + murano environment-model-show [--path ] [--session-id ] + + allows to get a specific section of the model, for example +`defaultNetworks`, `region` or `?` or any of the subsections. It defaults to +'/' which means getting the whole model. Specifying allows to get +the state of the environment with pending changes, while omitting it gives +the actual state. + +New CLI command that allows to update environment model with a custom patch: + +.. code-block:: shell + + murano environment-model-edit --session-id + +The command calls ``update_model`` method with data (JSON-patch) provided in +the file. Changes are to be saved in session . + +Alternatives +------------ + +Separate CLI command can be created for updating each environment property. +It will be somewhat easier for users because file with JSON-patch will not be +needed. On the other hand, it will require creating a bunch of commands +instead of one generic and necessity to add new commands in future for the +possible new properties. + +Data model impact +----------------- + +None + +REST API impact +--------------- + +**Get environment model** + ++----------+-------------------------------------+------------------------+--------------------------+ +| Method | URI | Header | Description | ++==========+=====================================+========================+==========================+ +| GET | /environments//model/ | X-Configuration-Session| Get an Environment model | +| | | (optional) | | ++----------+-------------------------------------+------------------------+--------------------------+ + +Specifying allows to get a specific section of the model, for example +`defaultNetworks`, `region` or `?` or any of the subsections. + +*Response* + +**Content-Type** + application/json + +:: + + { + "defaultNetworks": { + "environment": { + "internalNetworkName": "net_two", + "?": { + "type": "io.murano.resources.ExistingNeutronNetwork", + "id": "594e94fcfe4c48ef8f9b55edb3b9f177" + } + }, + "flat": null + }, + "region": "RegionTwo", + "name": "new_env", + "regions": { + "": { + "defaultNetworks": { + "environment": { + "autoUplink": true, + "name": "new_env-network", + "externalRouterId": null, + "dnsNameservers": [], + "autogenerateSubnet": true, + "subnetCidr": null, + "openstackId": null, + "?": { + "dependencies": { + "onDestruction": [{ + "subscriber": "c80e33dd67a44f489b2f04818b72f404", + "handler": null + }] + }, + "type": "io.murano.resources.NeutronNetwork/0.0.0@io.murano", + "id": "e145b50623c04a68956e3e656a0568d3", + "name": null + }, + "regionName": "RegionOne" + }, + "flat": null + }, + "name": "RegionOne", + "?": { + "type": "io.murano.CloudRegion/0.0.0@io.murano", + "id": "c80e33dd67a44f489b2f04818b72f404", + "name": null + } + }, + "RegionOne": "c80e33dd67a44f489b2f04818b72f404", + "RegionTwo": { + "defaultNetworks": { + "environment": { + "autoUplink": true, + "name": "new_env-network", + "externalRouterId": "e449bdd5-228c-4747-a925-18cda80fbd6b", + "dnsNameservers": ["8.8.8.8"], + "autogenerateSubnet": true, + "subnetCidr": "10.0.198.0/24", + "openstackId": "00a695c1-60ff-42ec-acb9-b916165413da", + "?": { + "dependencies": { + "onDestruction": [{ + "subscriber": "f8cb28d147914850978edb35eca156e1", + "handler": null + }] + }, + "type": "io.murano.resources.NeutronNetwork/0.0.0@io.murano", + "id": "72d2c13c600247c98e09e2e3c1cd9d70", + "name": null + }, + "regionName": "RegionTwo" + }, + "flat": null + }, + "name": "RegionTwo", + "?": { + "type": "io.murano.CloudRegion/0.0.0@io.murano", + "id": "f8cb28d147914850978edb35eca156e1", + "name": null + } + } + }, + services: [] + "?": { + "type": "io.murano.Environment/0.0.0@io.murano", + "_actions": { + "f7f22c174070455c9cafc59391402bdc_deploy": { + "enabled": true, + "name": "deploy", + "title": "deploy" + } + }, + "id": "f7f22c174070455c9cafc59391402bdc", + "name": null + } + } + ++----------------+-----------------------------------------------------------+ +| Code | Description | ++================+===========================================================+ +| 200 | Environment model received successfully | ++----------------+-----------------------------------------------------------+ +| 403 | User is not authorized to access environment | ++----------------+-----------------------------------------------------------+ +| 404 | Environment is not found or specified section of the | +| | model does not exist | ++----------------+-----------------------------------------------------------+ + +**Update environment model** + +*Request* + ++----------+--------------------------------+------------------------+-----------------------------+ +| Method | URI | Header | Description | ++==========+================================+========================+=============================+ +| PATCH | /environments//model/ | X-Configuration-Session| Update an Environment model | ++----------+--------------------------------+------------------------+-----------------------------+ + +* **Content-Type** + application/env-model-json-patch + +* **Example** + +:: + + [{ + "op": "replace", + "path": "/defaultNetworks/flat", + "value": true + }] + +*Response* + +**Content-Type** + application/json + +See GET request response. + ++----------------+-----------------------------------------------------------+ +| Code | Description | ++================+===========================================================+ +| 200 | Environment is edited successfully | ++----------------+-----------------------------------------------------------+ +| 400 | Body format is invalid | ++----------------+-----------------------------------------------------------+ +| 403 | User is not authorized to access environment or specified | +| | operation is forbidden for the given property | ++----------------+-----------------------------------------------------------+ +| 404 | Environment is not found or specified section of the | +| | model does not exist | ++----------------+-----------------------------------------------------------+ + +Versioning impact +----------------- + +None + +Other end user impact +--------------------- + +Users will get new CLI commands to examine and edit environment object model. + +Deployer impact +--------------- + +None + +Developer impact +---------------- + +None + +Murano-dashboard / Horizon impact +--------------------------------- + +New python-muranoclient method can be used for providing environment edit +capability from GUI, but this perspective is out of scope of this spec. + + +Implementation +============== + +Assignee(s) +----------- + +Primary assignee: + vakovalchuk + + +Work Items +---------- + +* Implement new API call to get object model of environment +* Implement new API calls to update the object model of environment +* Implement new python-muranoclient methods to support new API calls +* Add shell command that allows to display environment object model +* Add shell command that allows to apply JSON-patch to the environment model +* Add the same commands to the OpenStack client shell + + +Dependencies +============ + +None + + +Testing +======= + +* API calls should be tested by unit tests and tempest tests +* CLI commands should be tested by unit tests + + +Documentation Impact +==================== + +* API calls should be described in the Murano API specification +* CLI commands should be described in the end user guide + + +References +========== + +[1] https://tools.ietf.org/html/rfc6902