Charmed OpenSearch Tutorial > 4. Integrate with a client application
Integrate with a client application
Integrations (also known as “relations”) are the easiest way to connect to Charmed OpenSearch. Integrations automatically create a username, password, and database for the desired user/application, and define access permissions.
Summary
Deploy the Data Integrator charm
The best way to create a user and password for manual use (i.e. connecting to OpenSearch directly usingcurl
, which is what we’ll be doing later) is to add a relation between Charmed OpenSearch and the Data Integrator Charm.
Data Integrator is a bare-bones charm that allows for central management of database users, providing support for different kinds of data platform products (e.g. MongoDB, MySQL, PostgreSQL, Kafka, etc) with a consistent and robust user experience.
Deploy Data Integrator as follows:
juju deploy data-integrator --channel=edge --config index-name=test-index --config extra-user-roles=admin
The expected output:
Deployed "data-integrator" from charm-hub charm "data-integrator", revision 59 in channel latest/edge on ubuntu@22.04/stable
Wait for juju status --watch 1s
to show:
Model Controller Cloud/Region Version SLA Timestamp
tutorial opensearch-demo localhost/localhost 3.5.3 unsupported 12:43:22Z
App Version Status Scale Charm Channel Rev Exposed Message
data-integrator blocked 1 data-integrator latest/edge 59 no Please relate the data-integrator with the desired product
opensearch active 3 opensearch 2/beta 117 no
self-signed-certificates active 1 self-signed-certificates latest/stable 155 no
Unit Workload Agent Machine Public address Ports Message
data-integrator/0* blocked idle 4 10.95.38.22 Please relate the data-integrator with the desired product
opensearch/0* active idle 0 10.95.38.94 9200/tcp
opensearch/1 active idle 1 10.95.38.139 9200/tcp
opensearch/2 active idle 2 10.95.38.212 9200/tcp
self-signed-certificates/0* active idle 3 10.95.38.54
Machine State Address Inst id Base AZ Message
0 started 10.95.38.94 juju-be3883-0 ubuntu@22.04 Running
1 started 10.95.38.139 juju-be3883-1 ubuntu@22.04 Running
2 started 10.95.38.212 juju-be3883-2 ubuntu@22.04 Running
3 started 10.95.38.54 juju-be3883-3 ubuntu@22.04 Running
4 started 10.95.38.22 juju-be3883-4 ubuntu@22.04 Running
Integration provider Requirer Interface Type Message
data-integrator:data-integrator-peers data-integrator:data-integrator-peers data-integrator-peers peer
opensearch:node-lock-fallback opensearch:node-lock-fallback node_lock_fallback peer
opensearch:opensearch-peers opensearch:opensearch-peers opensearch_peers peer
opensearch:upgrade-version-a opensearch:upgrade-version-a upgrade peer
self-signed-certificates:certificates opensearch:certificates tls-certificates regular
Notice that the status of the data-integrator
application is blocked
. This is because it is waiting for a relation to be established with another application namely opensearch
.
Integrate with OpenSearch
Now that the Database Integrator charm has been set up, we can relate it to Charmed OpenSearch. This will automatically create a username, password, and CA certificate for the Database Integrator charm.
Integrate the two applications with:
juju integrate data-integrator opensearch
Wait for juju status --relations --watch 1s
to show that the data-integrator
application is now active:
Model Controller Cloud/Region Version SLA Timestamp
tutorial opensearch-demo localhost/localhost 3.5.3 unsupported 12:44:43Z
App Version Status Scale Charm Channel Rev Exposed Message
data-integrator active 1 data-integrator latest/edge 59 no
opensearch active 3 opensearch 2/beta 117 no
self-signed-certificates active 1 self-signed-certificates latest/stable 155 no
Unit Workload Agent Machine Public address Ports Message
data-integrator/0* active idle 4 10.95.38.22
opensearch/0* active idle 0 10.95.38.94 9200/tcp
opensearch/1 active idle 1 10.95.38.139 9200/tcp
opensearch/2 active idle 2 10.95.38.212 9200/tcp
self-signed-certificates/0* active idle 3 10.95.38.54
Machine State Address Inst id Base AZ Message
0 started 10.95.38.94 juju-be3883-0 ubuntu@22.04 Running
1 started 10.95.38.139 juju-be3883-1 ubuntu@22.04 Running
2 started 10.95.38.212 juju-be3883-2 ubuntu@22.04 Running
3 started 10.95.38.54 juju-be3883-3 ubuntu@22.04 Running
4 started 10.95.38.22 juju-be3883-4 ubuntu@22.04 Running
Integration provider Requirer Interface Type Message
data-integrator:data-integrator-peers data-integrator:data-integrator-peers data-integrator-peers peer
opensearch:node-lock-fallback opensearch:node-lock-fallback node_lock_fallback peer
opensearch:opensearch-client data-integrator:opensearch opensearch_client regular
opensearch:opensearch-peers opensearch:opensearch-peers opensearch_peers peer
opensearch:upgrade-version-a opensearch:upgrade-version-a upgrade peer
self-signed-certificates:certificates opensearch:certificates tls-certificates regular
Notice the new relation opensearch:opensearch-client data-integrator:opensearch opensearch_client regular
. This relation created the user, password, and CA certificate for the data-integrator
application.
To retrieve information such as the username, password, and database. Run the following command:
juju run data-integrator/leader get-credentials
This should output something like:
Running operation 1 with 1 task
- task 2 on unit-data-integrator-0
Waiting for task 2...
ok: "True"
opensearch:
data: '{"extra-user-roles": "admin", "index": "test-index", "requested-secrets":
"[\"username\", \"password\", \"tls\", \"tls-ca\", \"uris\"]"}'
endpoints: 10.95.38.139:9200,10.95.38.212:9200,10.95.38.94:9200
index: test-index
password: j3JWFnDkoumCxn0CtKZRCmdRMUlYTZFI
tls-ca: |-
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
username: opensearch-client_5
version: 2.14.0
Save the CA certificate (value of tls-ca
in the previous response), username, and password, because you will need them in the next section.
Create and access OpenSearch indices
Before connecting to OpenSearch, it is mandatory that you enable TLS on this cluster, following the previous step in the tutorial.
You can access the OpenSearch REST API in any way you prefer. In this tutorial, we will use curl
. Get the IP of an OpenSearch node from the output of juju status
(any of the nodes should work fine), and store the CA certificate in a local file (e.g. demo-ca.pem
). Then, run the following command to connect to the OpenSearch cluster:
curl --cacert demo-ca.pem -XGET https://username:password@opensearch_node_ip:9200/
Sending a GET
request to this /
endpoint should return some basic information about your OpenSearch deployment, which should look something like this:
{
"name" : "opensearch-2.0f3",
"cluster_name" : "opensearch-x3y6",
"cluster_uuid" : "yFS58g6hTbS0VxzJi0u7_g",
"version" : {
"distribution" : "opensearch",
"number" : "2.14.0",
"build_type" : "tar",
"build_hash" : "30dd870855093c9dca23fc6f8cfd5c0d7c83127d",
"build_date" : "2024-05-27T21:17:37.476666822Z",
"build_snapshot" : false,
"lucene_version" : "9.10.0",
"minimum_wire_compatibility_version" : "7.10.0",
"minimum_index_compatibility_version" : "7.0.0"
},
"tagline" : "The OpenSearch Project: https://opensearch.org/"
}
If this command fails, ensure the OpenSearch units are all in an active-idle state.
The command we ran used the --cacert
flag to pass in the CA chain generated by the TLS operator, ensuring secure and encrypted HTTP communications between our local host and the OpenSearch node.
To recap, the CA chain is generated by the TLS operator. It is passed over to the OpenSearch charm, which provides this certificate in its databag to any application that relates to it using the opensearch-client
relation interface. When developing charms that relate to the OpenSearch operator, make sure to use this certificate and the user credentials (username/password pair) to authenticate communications.
To index some data, run the following command:
curl --cacert demo-ca.pem \
-XPOST https://username:password@opensearch_node_ip:9200/albums/_doc/1?refresh=true \
-d '{"artist": "Vulfpeck", "genre": ["Funk", "Jazz"], "title": "Thrill of the Arts"}' \
-H 'Content-Type: application/json' -H 'Accept: application/json'
This command uses the same certificate and user credentials to send a POST
request to the same node as before, but it sends a specific JSON payload to a specific document address. The output should look like the following:
{
"_index": "albums",
"_id": "1",
"_version": 1,
"result": "created",
"forced_refresh": true,
"_shards": { "total": 2, "successful": 1, "failed": 0 },
"_seq_no": 0,
"_primary_term": 1
}
Note from the response that our request was successful and the document was indexed.
Use the following command to retrieve the previous document:
curl --cacert demo-ca.pem -XGET https://username:password@opensearch_node_ip:9200/albums/_doc/1
This call should output something like the following:
{
"_index": "albums",
"_id": "1",
"_version": 1,
"_seq_no": 0,
"_primary_term": 1,
"found": true,
"_source": {
"artist": "Vulfpeck",
"genre": ["Funk", "Jazz"],
"title": "Thrill of the Arts"
}
}
To add data in bulk using the OpenSearch Bulk API, copy and paste the following data into a file called bulk-albums.json
, ensuring that you keep the newline at the end of the file:
{ "index" : { "_index": "albums", "_id" : "2" } }
{"artist": "Herbie Hancock", "genre": ["Jazz"], "title": "Head Hunters"}
{ "index" : { "_index": "albums", "_id" : "3" } }
{"artist": "Lydian Collective", "genre": ["Jazz"], "title": "Adventure"}
{ "index" : { "_index": "albums", "_id" : "4" } }
{"artist": "Rush", "genre": ["Prog"], "title": "Moving Pictures"}
Then, to send this data to the bulk endpoint, run the following command:
curl --cacert demo-ca.pem -XPOST https://username:password@opensearch_node_ip:9200/_bulk --data-binary @bulk-albums.json -H 'Content-Type: application/json'
This should return a JSON response with the results of the bulk indexing operation:
{
"took": 17,
"errors": false,
"items": [ ... ]
}
What is of interest in the response is the errors
field. If it is false
, then the operation was successful. If it is true
, then there were errors in the bulk operation. The items
field contains the results of each operation in the bulk request.
To view the previously indexed documents, we can run a search query for the Jazz
keyword in our albums
index, using the following command:
curl --cacert demo-ca.pem -XGET https://username:password@opensearch_node_ip:9200/albums/_search?q=Jazz
This should return a JSON response with all the Jazz albums in the index:
{
"took": 35,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 3,
"relation": "eq"
},
"max_score": 0.4121628,
"hits": [
{
"_index": "albums",
"_id": "1",
"_score": 0.4121628,
"_source": {
"artist": "Vulfpeck",
"genre": ["Funk", "Jazz"],
"title": "Thrill of the Arts"
}
},
{
"_index": "albums",
"_id": "2",
"_score": 0.4121628,
"_source": {
"artist": "Herbie Hancock",
"genre": ["Jazz"],
"title": "Head Hunters"
}
},
{
"_index": "albums",
"_id": "3",
"_score": 0.4121628,
"_source": {
"artist": "Lydian Collective",
"genre": ["Jazz"],
"title": "Adventure"
}
}
]
}
}
Remove the user
To remove the user used in the previous calls, remove the relation. Removing the relation automatically removes the user created when the relation was created. Run the following to remove the relation:
juju remove-relation opensearch data-integrator
if you run juju status --relations
you will see that the relation has been removed and that the data-integrator
application is now in a blocked
state.
Model Controller Cloud/Region Version SLA Timestamp
tutorial opensearch-demo localhost/localhost 3.5.3 unsupported 13:48:08Z
App Version Status Scale Charm Channel Rev Exposed Message
data-integrator blocked 1 data-integrator latest/edge 59 no Please relate the data-integrator with the desired product
opensearch active 3 opensearch 2/beta 117 no
self-signed-certificates active 1 self-signed-certificates latest/stable 155 no
Unit Workload Agent Machine Public address Ports Message
data-integrator/0* blocked idle 4 10.95.38.22 Please relate the data-integrator with the desired product
opensearch/0* active idle 0 10.95.38.94 9200/tcp
opensearch/1 active idle 1 10.95.38.139 9200/tcp
opensearch/2 active idle 2 10.95.38.212 9200/tcp
self-signed-certificates/0* active idle 3 10.95.38.54
Machine State Address Inst id Base AZ Message
0 started 10.95.38.94 juju-be3883-0 ubuntu@22.04 Running
1 started 10.95.38.139 juju-be3883-1 ubuntu@22.04 Running
2 started 10.95.38.212 juju-be3883-2 ubuntu@22.04 Running
3 started 10.95.38.54 juju-be3883-3 ubuntu@22.04 Running
4 started 10.95.38.22 juju-be3883-4 ubuntu@22.04 Running
Integration provider Requirer Interface Type Message
data-integrator:data-integrator-peers data-integrator:data-integrator-peers data-integrator-peers peer
opensearch:node-lock-fallback opensearch:node-lock-fallback node_lock_fallback peer
opensearch:opensearch-peers opensearch:opensearch-peers opensearch_peers peer
opensearch:upgrade-version-a opensearch:upgrade-version-a upgrade peer
self-signed-certificates:certificates opensearch:certificates tls-certificates regular
Now try again to connect in the same way as the previous section
curl --cacert demo-ca.pem -XGET https://username:password@opensearch_node_ip:9200/
This should output something like the following error:
Unauthorized
If you wanted to recreate this user all you would need to do is relate the two applications and run the same action on data-integrator
to get the new credentials:
juju integrate data-integrator opensearch
juju run data-integrator/leader get-credentials
You can now connect to the database with this new username and password:
curl --cacert demo-ca.pem -XGET https://new_username:new_password@opensearch_node_ip:9200/albums/_search?q=Jazz
This should return the same response as before. The data in the database is not lost when the user is removed, only the user is removed.
Also, note that the certificate does not change across relations. To create a new certificate, remove the relation between opensearch
and the self-signed-certificates
operator, wait for opensearch
to enter a blocked status, and then recreate the relation. Run the get-credentials
action on the data-integrator charm again to get the new credentials, and test them again with the above search request.
Next step: 5. Manage passwords