Adding MongoDB charm 01/10201/2
authorsousaedu <eduardo.sousa@canonical.com>
Wed, 20 Jan 2021 16:09:48 +0000 (16:09 +0000)
committersousaedu <eduardo.sousa@canonical.com>
Wed, 20 Jan 2021 16:10:15 +0000 (16:10 +0000)
Change-Id: I23d491617525601587633d8338e09bcb9473f542
Signed-off-by: sousaedu <eduardo.sousa@canonical.com>
21 files changed:
installers/charm/mongodb-k8s/.gitignore [new file with mode: 0644]
installers/charm/mongodb-k8s/.yamllint.yaml [new file with mode: 0644]
installers/charm/mongodb-k8s/README.md [new file with mode: 0755]
installers/charm/mongodb-k8s/actions.yaml [new file with mode: 0644]
installers/charm/mongodb-k8s/actions/backup [new file with mode: 0755]
installers/charm/mongodb-k8s/actions/is-primary [new file with mode: 0755]
installers/charm/mongodb-k8s/actions/remove-backup [new file with mode: 0755]
installers/charm/mongodb-k8s/actions/restore [new file with mode: 0755]
installers/charm/mongodb-k8s/config.yaml [new file with mode: 0755]
installers/charm/mongodb-k8s/icon.svg [new file with mode: 0644]
installers/charm/mongodb-k8s/layer.yaml [new file with mode: 0644]
installers/charm/mongodb-k8s/metadata.yaml [new file with mode: 0755]
installers/charm/mongodb-k8s/reactive/mongo.py [new file with mode: 0644]
installers/charm/mongodb-k8s/reactive/spec_template.yaml [new file with mode: 0644]
installers/charm/mongodb-k8s/reactive/spec_template_ha.yaml [new file with mode: 0644]
installers/charm/mongodb-k8s/test-requirements.txt [new file with mode: 0644]
installers/charm/mongodb-k8s/tests/basic_deployment.py [new file with mode: 0644]
installers/charm/mongodb-k8s/tests/bundles/mongodb-ha.yaml [new file with mode: 0644]
installers/charm/mongodb-k8s/tests/bundles/mongodb.yaml [new file with mode: 0644]
installers/charm/mongodb-k8s/tests/tests.yaml [new file with mode: 0644]
installers/charm/mongodb-k8s/tox.ini [new file with mode: 0644]

diff --git a/installers/charm/mongodb-k8s/.gitignore b/installers/charm/mongodb-k8s/.gitignore
new file mode 100644 (file)
index 0000000..712eb96
--- /dev/null
@@ -0,0 +1,24 @@
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+release/
+__pycache__
+.tox
diff --git a/installers/charm/mongodb-k8s/.yamllint.yaml b/installers/charm/mongodb-k8s/.yamllint.yaml
new file mode 100644 (file)
index 0000000..21b95b5
--- /dev/null
@@ -0,0 +1,34 @@
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+---
+
+extends: default
+rules:
+  line-length: disable
+yaml-files:
+  - '*.yaml'
+  - '*.yml'
+  - '.yamllint'
+ignore: |
+ reactive/
+ .tox
+ release/
diff --git a/installers/charm/mongodb-k8s/README.md b/installers/charm/mongodb-k8s/README.md
new file mode 100755 (executable)
index 0000000..ce976d6
--- /dev/null
@@ -0,0 +1,175 @@
+<!-- Copyright 2021 Canonical Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may
+not use this file except in compliance with the License. You may obtain
+a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations
+under the License.
+
+For those usages not covered by the Apache License, Version 2.0 please
+contact: legal@canonical.com
+
+To get in touch with the maintainers, please contact:
+osm-charmers@lists.launchpad.net -->
+
+# Overview
+
+Mongo for Juju CAAS
+
+## Actions
+
+### Backup
+
+Execute the following steps to do a backup.
+
+```bash
+$ juju run-action mongodb-k8s/0 backup --wait
+unit-mongodb-k8s-0:
+  UnitId: mongodb-k8s/0
+  id: "7"
+  results:
+    Stderr: "2020-02-26T14:13:56.448+0000\twriting admin.system.version to archive
+      '/data/backup.archive'\n2020-02-26T14:13:56.451+0000\tdone dumping admin.system.version
+      (1 document)\n"
+    copy:
+      cmd: kubectl cp mongo-ha/mongodb-k8s-0:/data/backup.archive backup.archive
+    restore:
+      cmd: kubectl cp backup.archive mongo-ha/mongodb-k8s-0:/data/backup.archive
+      juju: juju action mongodb-k8s/0 restore --wait
+  status: completed
+  timing:
+    completed: 2020-02-26 14:13:57 +0000 UTC
+    enqueued: 2020-02-26 14:13:55 +0000 UTC
+    started: 2020-02-26 14:13:56 +0000 UTC
+$ kubectl cp mongo-ha/mongodb-k8s-0:/data/backup.archive backup.archive
+```
+
+> Additional note: You can add `--string-args target=PRIMARY|SECONDARY` if you want this action to be run in a specific mongo unit. If `SECONDARY` is set, but the mongo unit isn't the `SECONDARY`, the action will fail.
+
+### Restore
+
+When the backup function is executed, you will see the commands you need to execute for restoring from a backup.
+
+```bash
+$ kubectl cp backup.archive mongo-ha/mongodb-k8s-0:/data/backup.archive
+Defaulting container name to mongodb-k8s.
+$ juju run-action mongodb-k8s/0 restore --wait
+unit-mongodb-k8s-0:
+  UnitId: mongodb-k8s/0
+  id: "8"
+  results:
+    Stderr: "2020-02-26T14:17:00.300+0000\tpreparing collections to restore from\n2020-02-26T14:17:00.312+0000\t0
+      document(s) restored successfully. 0 document(s) failed to restore.\n"
+  status: completed
+  timing:
+    completed: 2020-02-26 14:17:01 +0000 UTC
+    enqueued: 2020-02-26 14:16:57 +0000 UTC
+    started: 2020-02-26 14:17:00 +0000 UTC
+```
+
+### Remove backup
+
+When a backup is made, it is stored in the unit. To easily remove the backup, execute this action:
+
+```bash
+$ juju run-action mongodb-k8s/0 remove-backup --wait
+unit-mongodb-k8s-0:
+  UnitId: mongodb-k8s/0
+  id: "4"
+  results:
+    Stdout: |
+      Backup successfully removed!
+  status: completed
+  timing:
+    completed: 2020-02-26 16:31:11 +0000 UTC
+    enqueued: 2020-02-26 16:31:08 +0000 UTC
+    started: 2020-02-26 16:31:10 +0000 UTC
+```
+
+### Is primary?
+
+To check if the unit is primary:
+
+```bash
+$ juju run-action mongodb-k8s/0 is-primary --wait
+unit-mongodb-k8s-0:
+  UnitId: mongodb-k8s/0
+  id: "5"
+  results:
+    unit:
+      ip: 10.1.31.92
+      primary: "true"
+  status: completed
+  timing:
+    completed: 2020-02-26 16:32:10 +0000 UTC
+    enqueued: 2020-02-26 16:32:08 +0000 UTC
+    started: 2020-02-26 16:32:09 +0000 UTC
+$ juju run-action mongodb-k8s/1 is-primary --wait
+unit-mongodb-k8s-1:
+  UnitId: mongodb-k8s/1
+  id: "6"
+  results:
+    unit:
+      ip: 10.1.31.93
+      primary: "false"
+  status: completed
+  timing:
+    completed: 2020-02-26 16:32:34 +0000 UTC
+    enqueued: 2020-02-26 16:32:32 +0000 UTC
+    started: 2020-02-26 16:32:33 +0000 UTC
+```
+
+## Backup remotely
+
+If we want to perform a backup remotely, follow the next steps:
+
+```bash
+$ sudo apt install mongo-tools-y
+$ juju status mongodb-k8s
+Model     Controller          Cloud/Region        Version  SLA          Timestamp
+mongo-ha  microk8s-localhost  microk8s/localhost  2.7.2    unsupported  16:26:02+01:00
+
+App          Version       Status  Scale  Charm        Store  Rev  OS          Address        Notes
+mongodb-k8s  mongo:latest  active      2  mongodb-k8s  local    0  kubernetes  10.152.183.90  
+
+Unit            Workload  Agent  Address     Ports      Message
+mongodb-k8s/0*  active    idle   10.1.31.75  27017/TCP  ready
+mongodb-k8s/1   active    idle   10.1.31.76  27017/TCP  ready
+$ mongodump --host 10.152.183.90 --port 27017 --gzip --archive=backup.archive --forceTableScan
+2020-02-26T16:41:23.777+0100    writing admin.system.version to archive 'backup.archive'
+2020-02-26T16:41:23.779+0100    done dumping admin.system.version (1 document)
+$ mongorestore --host 10.152.183.90 --port 27017 --gzip --archive=backup.archive
+```
+
+## Testing
+
+The tests of this charm are done using tox and Zaza.
+
+### Prepare environment
+
+The machine in which the tests are run needs access to a juju k8s controller. The easiest way to approach this is by executing the following commands:
+
+```bash
+sudo apt install tox -y
+sudo snap install microk8s --classic
+sudo snap install juju
+
+microk8s.status --wait-ready
+microk8s.enable storage dashboard dns
+
+juju bootstrap microk8s k8s-cloud
+```
+
+### Test charm with Tox
+
+```bash
+tox -e black    # Check syntax
+tox -e build    # Build the charm
+tox -e func     # Test charm
+```
diff --git a/installers/charm/mongodb-k8s/actions.yaml b/installers/charm/mongodb-k8s/actions.yaml
new file mode 100644 (file)
index 0000000..b857242
--- /dev/null
@@ -0,0 +1,48 @@
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+backup:
+  description: "Do a mongodb backup"
+  params:
+    target:
+      description: "The unit in which it should be performed the action. (ANY, PRIMARY, SECONDARY)"
+      type: string
+      default: "ANY"
+    path:
+      description: "Path for the backup inside the unit"
+      type: string
+      default: "/data"
+restore:
+  description: "Restore from a MongoDB Backup"
+  params:
+    path:
+      description: "Path for the backup inside the unit"
+      type: string
+      default: "/data"
+remove-backup:
+  description: "Remove backup from unit"
+  params:
+    path:
+      description: "Path for the backup inside the unit"
+      type: string
+      default: "/data"
+is-primary:
+  description: "Check if the unit is the primary"
diff --git a/installers/charm/mongodb-k8s/actions/backup b/installers/charm/mongodb-k8s/actions/backup
new file mode 100755 (executable)
index 0000000..bd51d03
--- /dev/null
@@ -0,0 +1,46 @@
+#!/bin/bash
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+MASTER=`mongo --quiet --eval "d=db.isMaster(); print( d['ismaster'] );"`
+
+TARGET=`action-get target` 
+DB_BACKUP_PATH=`action-get path`
+
+mkdir -p $DB_BACKUP_PATH
+
+if [ "$TARGET" == "SECONDARY" ]; then
+    if [ "$MASTER" == "true" ]; then
+        action-fail "This action should be run in a Secondary"
+        exit
+    fi
+elif [ "$TARGET" == "PRIMARY" ]; then
+    if [ "$MASTER" == "false" ]; then
+        action-fail "This action should be run in a Primary"
+        exit
+    fi
+fi
+
+mongodump --gzip --archive=$DB_BACKUP_PATH/backup.archive
+action-set copy.cmd="kubectl cp $JUJU_MODEL_NAME/$HOSTNAME:$DB_BACKUP_PATH/backup.archive backup.archive"
+action-set restore.cmd="kubectl cp backup.archive $JUJU_MODEL_NAME/$HOSTNAME:$DB_BACKUP_PATH/backup.archive"
+action-set restore.juju="juju run-action $JUJU_UNIT_NAME restore --wait"
+
diff --git a/installers/charm/mongodb-k8s/actions/is-primary b/installers/charm/mongodb-k8s/actions/is-primary
new file mode 100755 (executable)
index 0000000..2e8477b
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/bash
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+MASTER=`mongo --quiet --eval "d=db.isMaster(); print( d['ismaster'] );"`
+action-set unit.primary=$MASTER
+action-set unit.ip=`network-get mongo --bind-address`
\ No newline at end of file
diff --git a/installers/charm/mongodb-k8s/actions/remove-backup b/installers/charm/mongodb-k8s/actions/remove-backup
new file mode 100755 (executable)
index 0000000..71918ed
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/bash
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+DB_BACKUP_PATH=`action-get path`
+rm $DB_BACKUP_PATH/backup.archive || exit
+echo Backup successfully removed!
diff --git a/installers/charm/mongodb-k8s/actions/restore b/installers/charm/mongodb-k8s/actions/restore
new file mode 100755 (executable)
index 0000000..8ce7c3a
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/bash
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+DB_BACKUP_PATH=`action-get path`
+mongorestore --gzip --archive=$DB_BACKUP_PATH/backup.archive
+
diff --git a/installers/charm/mongodb-k8s/config.yaml b/installers/charm/mongodb-k8s/config.yaml
new file mode 100755 (executable)
index 0000000..74e3fc2
--- /dev/null
@@ -0,0 +1,58 @@
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+options:
+  advertised-hostname:
+    description: MongoDB Hostname
+    type: string
+    default: mongodb-k8s
+  advertised-port:
+    description: MongoDB port
+    type: int
+    default: 27017
+  replica-set:
+    description: Mongo Replica-set name
+    type: string
+    default: rs0
+  namespace:
+    description: Kubernetes namespace
+    type: string
+    default: osm
+  service-name:
+    description: Headless service name
+    type: string
+    default: mongodb-k8s-endpoints
+  cluster-domain:
+    description: Cluster domain
+    type: string
+    default: cluster.local
+  enable-sidecar:
+    description: Enable sidecar
+    type: boolean
+    default: false
+  mongodb-image:
+    type: string
+    description: OCI image
+    default: rocks.canonical.com:443/mongo:latest
+  sidecar-image:
+    type: string
+    description: OCI image
+    default: rocks.canonical.com:443/cvallance/mongo-k8s-sidecar:latest
diff --git a/installers/charm/mongodb-k8s/icon.svg b/installers/charm/mongodb-k8s/icon.svg
new file mode 100644 (file)
index 0000000..811be4f
--- /dev/null
@@ -0,0 +1,395 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg6517"
+   version="1.1"
+   inkscape:version="0.91+devel r"
+   sodipodi:docname="mongoDB.svg"
+   viewBox="0 0 96 96">
+  <defs
+     id="defs6519">
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient896">
+      <stop
+         style="stop-color:#198332;stop-opacity:1"
+         offset="0"
+         id="stop898" />
+      <stop
+         style="stop-color:#24933b;stop-opacity:1"
+         offset="1"
+         id="stop900" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient888">
+      <stop
+         style="stop-color:#0f9b36;stop-opacity:1"
+         offset="0"
+         id="stop890" />
+      <stop
+         style="stop-color:#64bb66;stop-opacity:1"
+         offset="1"
+         id="stop892" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient878">
+      <stop
+         style="stop-color:#e3e2ce;stop-opacity:1"
+         offset="0"
+         id="stop880" />
+      <stop
+         id="stop886"
+         offset="0.45080602"
+         style="stop-color:#ceceb5;stop-opacity:1;" />
+      <stop
+         style="stop-color:#95966f;stop-opacity:1"
+         offset="1"
+         id="stop882" />
+    </linearGradient>
+    <linearGradient
+       id="Background">
+      <stop
+         id="stop4178"
+         offset="0"
+         style="stop-color:#22779e;stop-opacity:1" />
+      <stop
+         id="stop4180"
+         offset="1"
+         style="stop-color:#2991c0;stop-opacity:1" />
+    </linearGradient>
+    <filter
+       style="color-interpolation-filters:sRGB"
+       inkscape:label="Inner Shadow"
+       id="filter1121">
+      <feFlood
+         flood-opacity="0.59999999999999998"
+         flood-color="rgb(0,0,0)"
+         result="flood"
+         id="feFlood1123" />
+      <feComposite
+         in="flood"
+         in2="SourceGraphic"
+         operator="out"
+         result="composite1"
+         id="feComposite1125" />
+      <feGaussianBlur
+         in="composite1"
+         stdDeviation="1"
+         result="blur"
+         id="feGaussianBlur1127" />
+      <feOffset
+         dx="0"
+         dy="2"
+         result="offset"
+         id="feOffset1129" />
+      <feComposite
+         in="offset"
+         in2="SourceGraphic"
+         operator="atop"
+         result="composite2"
+         id="feComposite1131" />
+    </filter>
+    <filter
+       style="color-interpolation-filters:sRGB"
+       inkscape:label="Drop Shadow"
+       id="filter950">
+      <feFlood
+         flood-opacity="0.25"
+         flood-color="rgb(0,0,0)"
+         result="flood"
+         id="feFlood952" />
+      <feComposite
+         in="flood"
+         in2="SourceGraphic"
+         operator="in"
+         result="composite1"
+         id="feComposite954" />
+      <feGaussianBlur
+         in="composite1"
+         stdDeviation="1"
+         result="blur"
+         id="feGaussianBlur956" />
+      <feOffset
+         dx="0"
+         dy="1"
+         result="offset"
+         id="feOffset958" />
+      <feComposite
+         in="SourceGraphic"
+         in2="offset"
+         operator="over"
+         result="composite2"
+         id="feComposite960" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath873">
+      <g
+         transform="matrix(0,-0.66666667,0.66604479,0,-258.25992,677.00001)"
+         id="g875"
+         inkscape:label="Layer 1"
+         style="display:inline;fill:#ff00ff;fill-opacity:1;stroke:none">
+        <path
+           style="display:inline;fill:#ff00ff;fill-opacity:1;stroke:none"
+           d="M 46.702703,898.22775 H 97.297297 C 138.16216,898.22775 144,904.06497 144,944.92583 v 50.73846 c 0,40.86071 -5.83784,46.69791 -46.702703,46.69791 H 46.702703 C 5.8378378,1042.3622 0,1036.525 0,995.66429 v -50.73846 c 0,-40.86086 5.8378378,-46.69808 46.702703,-46.69808 z"
+           id="path877"
+           inkscape:connector-curvature="0"
+           sodipodi:nodetypes="sssssssss" />
+      </g>
+    </clipPath>
+    <style
+       id="style867"
+       type="text/css"><![CDATA[
+    .fil0 {fill:#1F1A17}
+   ]]></style>
+    <clipPath
+       id="clipPath16">
+      <path
+         id="path18"
+         d="M -9,-9 H 605 V 222 H -9 Z"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       id="clipPath116">
+      <path
+         id="path118"
+         d="m 91.7368,146.3253 -9.7039,-1.577 -8.8548,-3.8814 -7.5206,-4.7308 -7.1566,-8.7335 -4.0431,-4.282 -3.9093,-1.4409 -1.034,2.5271 1.8079,2.6096 0.4062,3.6802 1.211,-0.0488 1.3232,-1.2069 -0.3569,3.7488 -1.4667,0.9839 0.0445,1.4286 -3.4744,-1.9655 -3.1462,-3.712 -0.6559,-3.3176 1.3453,-2.6567 1.2549,-4.5133 2.5521,-1.2084 2.6847,0.1318 2.5455,1.4791 -1.698,-8.6122 1.698,-9.5825 -1.8692,-4.4246 -6.1223,-6.5965 1.0885,-3.941 2.9002,-4.5669 5.4688,-3.8486 2.9007,-0.3969 3.225,-0.1094 -2.012,-8.2601 7.3993,-3.0326 9.2188,-1.2129 3.1535,2.0619 0.2427,5.5797 3.5178,5.8224 0.2426,4.6094 8.4909,-0.6066 7.8843,0.7279 -7.8843,-4.7307 1.3343,-5.701 4.9731,-7.763 4.8521,-2.0622 3.8814,1.5769 1.577,3.1538 8.1269,6.1861 1.5769,-1.3343 12.7363,-0.485 2.5473,2.0619 0.2426,3.6391 -0.849,1.5767 -0.6066,9.8251 -4.2454,8.4909 0.7276,3.7605 2.5475,-1.3343 7.1566,-6.6716 3.5175,-0.2424 3.8815,1.5769 3.8818,2.9109 1.9406,6.3077 11.4021,-0.7277 6.914,2.6686 5.5797,5.2157 4.0028,7.5206 0.9706,8.8546 -0.8493,10.3105 -2.1832,9.2185 -2.1836,2.9112 -3.0322,0.9706 -5.3373,-5.8224 -4.8518,-1.6982 -4.2455,7.0353 -4.2454,3.8815 -2.3049,1.4556 -9.2185,7.6419 -7.3993,4.0028 -7.3993,0.6066 -8.6119,-1.4556 -7.5206,-2.7899 -5.2158,-4.2454 -4.1241,-4.9734 -4.2454,-1.2129"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       id="clipPath128">
+      <path
+         id="path130"
+         d="m 91.7368,146.3253 -9.7039,-1.577 -8.8548,-3.8814 -7.5206,-4.7308 -7.1566,-8.7335 -4.0431,-4.282 -3.9093,-1.4409 -1.034,2.5271 1.8079,2.6096 0.4062,3.6802 1.211,-0.0488 1.3232,-1.2069 -0.3569,3.7488 -1.4667,0.9839 0.0445,1.4286 -3.4744,-1.9655 -3.1462,-3.712 -0.6559,-3.3176 1.3453,-2.6567 1.2549,-4.5133 2.5521,-1.2084 2.6847,0.1318 2.5455,1.4791 -1.698,-8.6122 1.698,-9.5825 -1.8692,-4.4246 -6.1223,-6.5965 1.0885,-3.941 2.9002,-4.5669 5.4688,-3.8486 2.9007,-0.3969 3.225,-0.1094 -2.012,-8.2601 7.3993,-3.0326 9.2188,-1.2129 3.1535,2.0619 0.2427,5.5797 3.5178,5.8224 0.2426,4.6094 8.4909,-0.6066 7.8843,0.7279 -7.8843,-4.7307 1.3343,-5.701 4.9731,-7.763 4.8521,-2.0622 3.8814,1.5769 1.577,3.1538 8.1269,6.1861 1.5769,-1.3343 12.7363,-0.485 2.5473,2.0619 0.2426,3.6391 -0.849,1.5767 -0.6066,9.8251 -4.2454,8.4909 0.7276,3.7605 2.5475,-1.3343 7.1566,-6.6716 3.5175,-0.2424 3.8815,1.5769 3.8818,2.9109 1.9406,6.3077 11.4021,-0.7277 6.914,2.6686 5.5797,5.2157 4.0028,7.5206 0.9706,8.8546 -0.8493,10.3105 -2.1832,9.2185 -2.1836,2.9112 -3.0322,0.9706 -5.3373,-5.8224 -4.8518,-1.6982 -4.2455,7.0353 -4.2454,3.8815 -2.3049,1.4556 -9.2185,7.6419 -7.3993,4.0028 -7.3993,0.6066 -8.6119,-1.4556 -7.5206,-2.7899 -5.2158,-4.2454 -4.1241,-4.9734 -4.2454,-1.2129"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <linearGradient
+       id="linearGradient3850"
+       inkscape:collect="always">
+      <stop
+         id="stop3852"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop3854"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3095">
+      <path
+         d="M 976.648,389.551 H 134.246 V 1229.55 H 976.648 V 389.551"
+         id="path3097"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3195">
+      <path
+         d="m 611.836,756.738 -106.34,105.207 c -8.473,8.289 -13.617,20.102 -13.598,33.379 L 598.301,790.207 c -0.031,-13.418 5.094,-25.031 13.535,-33.469"
+         id="path3197"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3235">
+      <path
+         d="m 1095.64,1501.81 c 35.46,-35.07 70.89,-70.11 106.35,-105.17 4.4,-4.38 7.11,-10.53 7.11,-17.55 l -106.37,105.21 c 0,7 -2.71,13.11 -7.09,17.51"
+         id="path3237"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       id="clipPath4591"
+       clipPathUnits="userSpaceOnUse">
+      <path
+         inkscape:connector-curvature="0"
+         d="m 1106.6009,730.43734 -0.036,21.648 c -0.01,3.50825 -2.8675,6.61375 -6.4037,6.92525 l -83.6503,7.33162 c -3.5205,0.30763 -6.3812,-2.29987 -6.3671,-5.8145 l 0.036,-21.6475 20.1171,-1.76662 -0.011,4.63775 c 0,1.83937 1.4844,3.19925 3.3262,3.0395 l 49.5274,-4.33975 c 1.8425,-0.166 3.3425,-1.78125 3.3538,-3.626 l 0.01,-4.63025 20.1,-1.7575"
+         style="fill:#ff00ff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path4593" />
+    </clipPath>
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1.4333926,-2.2742838,1.1731823,-0.73941125,-174.08025,98.374394)"
+       r="20.40658"
+       fy="93.399292"
+       fx="-26.508606"
+       cy="93.399292"
+       cx="-26.508606"
+       id="radialGradient3856"
+       xlink:href="#linearGradient3850"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="translate(-318.48033,212.32022)"
+       gradientUnits="userSpaceOnUse"
+       y2="993.19702"
+       x2="-51.879555"
+       y1="593.11615"
+       x1="348.20132"
+       id="linearGradient3895"
+       xlink:href="#linearGradient3850"
+       inkscape:collect="always" />
+    <clipPath
+       id="clipPath3906"
+       clipPathUnits="userSpaceOnUse">
+      <rect
+         transform="scale(1,-1)"
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.8;fill:#ff00ff;stroke:none;stroke-width:4;marker:none;enable-background:accumulate"
+         id="rect3908"
+         width="1019.1371"
+         height="1019.1371"
+         x="357.9816"
+         y="-1725.8152" />
+    </clipPath>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient878"
+       id="linearGradient884"
+       x1="-856.05945"
+       y1="917.14075"
+       x2="-897.81281"
+       y2="890.35901"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient888"
+       id="linearGradient894"
+       x1="-1031.014"
+       y1="698.59906"
+       x2="-871.2926"
+       y2="549.73865"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient896"
+       id="linearGradient902"
+       x1="-845.72949"
+       y1="857.26373"
+       x2="-845.85956"
+       y2="536.13733"
+       gradientUnits="userSpaceOnUse" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="5.0931702"
+     inkscape:cx="-18.232516"
+     inkscape:cy="4.2657717"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="1920"
+     inkscape:window-height="1029"
+     inkscape:window-x="0"
+     inkscape:window-y="24"
+     inkscape:window-maximized="1"
+     showborder="true"
+     showguides="false"
+     inkscape:guide-bbox="true"
+     inkscape:showpageshadow="false"
+     inkscape:snap-global="true"
+     inkscape:snap-bbox="true"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:snap-bbox-midpoints="true"
+     inkscape:object-paths="true"
+     inkscape:snap-intersection-paths="true"
+     inkscape:object-nodes="true"
+     inkscape:snap-smooth-nodes="true"
+     inkscape:snap-midpoints="true"
+     inkscape:snap-object-midpoints="true"
+     inkscape:snap-center="true"
+     inkscape:snap-page="true">
+    <inkscape:grid
+       type="xygrid"
+       id="grid821" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="16,48"
+       id="guide823"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="64,80"
+       id="guide825"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="80,40"
+       id="guide827"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="64,16"
+       id="guide829"
+       inkscape:locked="false" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata6522">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="BACKGROUND"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(268,-635.29076)"
+     style="display:inline">
+    <path
+       style="display:inline;fill:#513721;fill-opacity:1;stroke:none"
+       d="M 48 0 A 48 48 0 0 0 0 48 A 48 48 0 0 0 48 96 A 48 48 0 0 0 96 48 A 48 48 0 0 0 48 0 z "
+       transform="translate(-268,635.29076)"
+       id="path6455" />
+    <g
+       id="g904"
+       transform="matrix(0.18303902,0,0,0.18303902,-61.510334,551.26852)"
+       style="filter:url(#filter950)">
+      <path
+         sodipodi:nodetypes="cssccccssc"
+         inkscape:connector-curvature="0"
+         id="path1268"
+         d="m -868.19899,524.60454 c -1.09201,-0.17404 2.2458,6.31938 -5.76173,16.46507 -8.62836,10.93231 -78.08998,55.87715 -80.25267,176.97194 -1.47326,82.49185 63.69591,140.08497 80.26221,150.82239 0,0 6.10773,21.21068 6.30878,46.24185 l 10.94779,2.8528 c -1.30685,-25.73485 -1.6868,-40.61122 5.75219,-51.97075 10.43063,-4.90853 76.14358,-61.15169 73.3404,-148.11885 -3.3392,-103.59672 -61.5131,-148.52136 -78.06619,-170.12132 -7.15576,-9.33748 -10.21866,-22.94207 -12.53078,-23.14313 z"
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient884);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:12;marker:none;enable-background:accumulate" />
+      <path
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient902);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:12;marker:none;enable-background:accumulate"
+         d="m -868.19899,524.60454 c 6.02168,19.47655 4.90908,108.16194 6.20984,193.26637 1.17969,77.18297 -13.32661,137.08201 11.04673,148.11693 10.43063,-4.90853 76.14358,-61.15169 73.3404,-148.11885 -3.3392,-103.59672 -61.5131,-148.52136 -78.06619,-170.12132 -7.15576,-9.33748 -10.21866,-22.94207 -12.53078,-23.14313 z"
+         id="path871"
+         inkscape:connector-curvature="0"
+         sodipodi:nodetypes="cscssc" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path873"
+         d="m -868.1875,524.60326 c -1.09201,-0.17404 2.22628,6.32306 -5.78125,16.46875 -8.62836,10.93231 -78.08731,55.87396 -80.25,176.96875 -1.47326,82.49185 63.71495,140.07508 80.28125,150.8125 4.55456,-2.09183 6.73773,-23.58984 8.71875,-48.5 0.1491,-26.4041 3.83655,-62.04848 3.21875,-102.46875 -1.21946,-79.7854 -0.31201,-162.74064 -5.15625,-188.84375 -0.0125,-0.0672 -0.0187,-0.12101 -0.0312,-0.1875 -0.32738,-1.41709 -0.65813,-2.83452 -1.00005,-4.25 z"
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient894);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:12;marker:none;enable-background:accumulate" />
+    </g>
+  </g>
+</svg>
diff --git a/installers/charm/mongodb-k8s/layer.yaml b/installers/charm/mongodb-k8s/layer.yaml
new file mode 100644 (file)
index 0000000..3ffabb9
--- /dev/null
@@ -0,0 +1,29 @@
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+includes:
+  - "layer:caas-base"
+  - 'layer:status'
+  - 'layer:leadership'
+  - "layer:osm-common"
+  - 'interface:mongodb'
+
+repo: https://code.launchpad.net/osm-k8s-bundle
diff --git a/installers/charm/mongodb-k8s/metadata.yaml b/installers/charm/mongodb-k8s/metadata.yaml
new file mode 100755 (executable)
index 0000000..4e27906
--- /dev/null
@@ -0,0 +1,41 @@
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+name: "mongodb-k8s"
+summary: "MongoDB charm for Kubernetes."
+maintainers:
+    - "SolutionsQA <solutionsqa@lists.canonical.com>"
+description: |
+    A CAAS charm to deploy MongoDB.
+tags:
+    - "application"
+series:
+    - "kubernetes"
+provides:
+    mongo:
+        interface: mongodb
+storage:
+    database:
+        type: filesystem
+        location: /data/db
+deployment:
+    type: stateful
+    service: cluster
diff --git a/installers/charm/mongodb-k8s/reactive/mongo.py b/installers/charm/mongodb-k8s/reactive/mongo.py
new file mode 100644 (file)
index 0000000..026f5ed
--- /dev/null
@@ -0,0 +1,128 @@
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+from charms.layer.caas_base import pod_spec_set
+from charms.reactive import endpoint_from_flag
+from charms.reactive import when, when_not, hook
+from charms.reactive.flags import set_flag, clear_flag
+from charmhelpers.core.hookenv import log, metadata, config, goal_state
+from charms import layer
+
+
+@hook("upgrade-charm")
+@when("leadership.is_leader")
+def upgrade():
+    clear_flag("mongodb-k8s.configured")
+
+
+@when("config.changed")
+@when("leadership.is_leader")
+def restart():
+    clear_flag("mongodb-k8s.configured")
+
+
+@when_not("mongodb-k8s.configured")
+@when("leadership.is_leader")
+def configure():
+    layer.status.maintenance("Configuring MongoDB container")
+    try:
+        spec = make_pod_spec()
+        log("set pod spec:\n{}".format(spec))
+        pod_spec_set(spec)
+        set_flag("mongodb-k8s.configured")
+    except Exception as e:
+        layer.status.blocked("k8s spec failed to deploy: {}".format(e))
+
+
+@when("mongodb-k8s.configured")
+def set_mongodb_active():
+    layer.status.active("ready")
+
+
+@when_not("leadership.is_leader")
+def non_leaders_active():
+    layer.status.active("ready")
+
+
+@when("mongodb-k8s.configured", "mongo.joined")
+def send_config():
+    layer.status.maintenance("Sending mongo configuration")
+    try:
+        mongo = endpoint_from_flag("mongo.joined")
+        if mongo:
+            cfg = config()
+            mongo_uri = "mongodb://"
+            for i, unit in enumerate(goal_state()["units"]):
+                pod_base_name = unit.split("/")[0]
+                service_name = cfg.get("service-name")
+                pod_name = "{}-{}".format(pod_base_name, i)
+                if i:
+                    mongo_uri += ","
+                mongo_uri += "{}.{}:{}".format(
+                    pod_name, service_name, get_mongodb_port()
+                )
+            if cfg.get("enable-sidecar"):
+                mongo_uri += "/?replicaSet={}".format(get_mongodb_replset())
+            log("Mongo URI: {}".format(mongo_uri))
+            mongo.send_connection_string(mongo_uri)
+            clear_flag("mongo.joined")
+    except Exception as e:
+        log("Exception sending config: {}".format(e))
+        clear_flag("mongo.joined")
+
+
+def make_pod_spec():
+    """Make pod specification for Kubernetes
+
+    Returns:
+        pod_spec: Pod specification for Kubernetes
+    """
+    md = metadata()
+    cfg = config()
+
+    if cfg.get("enable-sidecar"):
+        with open("reactive/spec_template_ha.yaml") as spec_file:
+            pod_spec_template = spec_file.read()
+    else:
+        with open("reactive/spec_template.yaml") as spec_file:
+            pod_spec_template = spec_file.read()
+
+    data = {
+        "name": md.get("name"),
+        "docker_image": cfg.get("mongodb-image"),
+        "sc_docker_image": cfg.get("sidecar-image"),
+        "pod_labels": "juju-app={}".format(cfg.get("advertised-hostname")),
+    }
+
+    data.update(cfg)
+    return pod_spec_template % data
+
+
+def get_mongodb_port():
+    """Returns MongoDB port"""
+    cfg = config()
+    return cfg.get("advertised-port")
+
+
+def get_mongodb_replset():
+    """Returns MongoDB port"""
+    cfg = config()
+    return cfg.get("replica-set")
diff --git a/installers/charm/mongodb-k8s/reactive/spec_template.yaml b/installers/charm/mongodb-k8s/reactive/spec_template.yaml
new file mode 100644 (file)
index 0000000..035e9fb
--- /dev/null
@@ -0,0 +1,49 @@
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+version: 2
+containers:
+  - name: %(name)s
+    image: %(docker_image)s
+    command:
+      - mongod
+      - "--bind_ip"
+      - "0.0.0.0"
+    ports:
+    - containerPort: %(advertised-port)s
+      protocol: TCP
+    config:
+      ALLOW_ANONYMOUS_LOGIN: 'yes'
+    kubernetes:
+      readinessProbe:
+        tcpSocket:
+          port: %(advertised-port)s
+        timeoutSeconds: 5
+        periodSeconds: 5
+        initialDelaySeconds: 10
+      livenessProbe:
+        exec:
+          command:
+            - /bin/sh
+            - -c
+            - mongo --port %(advertised-port)s --eval "rs.status()" | grep -vq "REMOVED"
+        initialDelaySeconds: 45
+        timeoutSeconds: 5
diff --git a/installers/charm/mongodb-k8s/reactive/spec_template_ha.yaml b/installers/charm/mongodb-k8s/reactive/spec_template_ha.yaml
new file mode 100644 (file)
index 0000000..60c44d4
--- /dev/null
@@ -0,0 +1,63 @@
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+version: 2
+serviceAccount:
+  rules:
+    - apiGroups: [""]
+      resources: ["pods"]
+      verbs: ["list"]
+containers:
+  - name: %(name)s
+    image: %(docker_image)s
+    command:
+      - mongod
+      - "--replSet"
+      - %(replica-set)s
+      - "--bind_ip"
+      - "0.0.0.0"
+    ports:
+    - containerPort: %(advertised-port)s
+      protocol: TCP
+    config:
+      ALLOW_ANONYMOUS_LOGIN: 'yes'
+    kubernetes:
+      readinessProbe:
+        tcpSocket:
+          port: %(advertised-port)s
+        timeoutSeconds: 5
+        periodSeconds: 5
+        initialDelaySeconds: 10
+      livenessProbe:
+        exec:
+          command:
+            - /bin/sh
+            - -c
+            - mongo --port %(advertised-port)s --eval "rs.status()" | grep -vq "REMOVED"
+        initialDelaySeconds: 45
+        timeoutSeconds: 5
+  - name: 'mongodb-sidecar-k8s'
+    image: %(sc_docker_image)s
+    config:
+      KUBERNETES_MONGO_SERVICE_NAME: %(service-name)s
+      KUBE_NAMESPACE: %(namespace)s
+      MONGO_SIDECAR_POD_LABELS: %(pod_labels)s
+      KUBERNETES_CLUSTER_DOMAIN: %(cluster-domain)s
\ No newline at end of file
diff --git a/installers/charm/mongodb-k8s/test-requirements.txt b/installers/charm/mongodb-k8s/test-requirements.txt
new file mode 100644 (file)
index 0000000..4aac56d
--- /dev/null
@@ -0,0 +1,23 @@
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+git+https://github.com/davigar15/zaza.git#egg=zaza
+pymongo
\ No newline at end of file
diff --git a/installers/charm/mongodb-k8s/tests/basic_deployment.py b/installers/charm/mongodb-k8s/tests/basic_deployment.py
new file mode 100644 (file)
index 0000000..3a8e9a3
--- /dev/null
@@ -0,0 +1,122 @@
+#!/usr/bin/python3
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+import unittest
+import zaza.model as model
+from pymongo import MongoClient
+
+
+def get_mongo_uri():
+    mongo_uri = "mongodb://"
+    mongo_units = model.get_status().applications["mongodb-k8s"]["units"]
+    for i, unit_name in enumerate(mongo_units.keys()):
+        if i:
+            mongo_uri += ","
+        unit_ip = mongo_units[unit_name]["address"]
+        unit_port = mongo_units[unit_name]["opened-ports"][0].split("/")[0]
+        mongo_uri += "{}:{}".format(unit_ip, unit_port)
+
+    return mongo_uri
+
+
+class BasicDeployment(unittest.TestCase):
+    def test_get_mongo_uri(self):
+        get_mongo_uri()
+
+    def test_mongodb_connection(self):
+        mongo_uri = get_mongo_uri()
+        client = MongoClient(mongo_uri)
+        client.server_info()
+
+    def test_mongodb_create_empty_database_collection(self):
+        mongo_uri = get_mongo_uri()
+        client = MongoClient(mongo_uri)
+        DB_NAME = "test_database"
+        COLLECTION_NAME = "test_collection"
+
+        db = client[DB_NAME]
+        _ = client.list_database_names()
+
+        collection = db[COLLECTION_NAME]
+        _ = db.list_collection_names()
+
+        data = {}
+
+        id = collection.insert_one(data)
+
+        for x in collection.find({"_id": id.inserted_id}):
+            self.assertEqual(id.inserted_id, x["_id"])
+
+    def test_mongodb_insert_one(self):
+        mongo_uri = get_mongo_uri()
+        client = MongoClient(mongo_uri)
+        DB_NAME = "test_database"
+        COLLECTION_NAME = "test_collection"
+
+        db = client[DB_NAME]
+        _ = client.list_database_names()
+
+        collection = db[COLLECTION_NAME]
+        _ = db.list_collection_names()
+
+        data = {
+            "name": "Canonical LTD",
+            "address": "5th Floor of the Blue Fin Building",
+        }
+
+        id = collection.insert_one(data)
+
+        for x in collection.find({"_id": id.inserted_id}):
+            self.assertEqual(id.inserted_id, x["_id"])
+
+    def test_mongodb_insert_many(self):
+        mongo_uri = get_mongo_uri()
+        client = MongoClient(mongo_uri)
+        DB_NAME = "test_database"
+        COLLECTION_NAME = "test_collection"
+
+        db = client[DB_NAME]
+        _ = client.list_database_names()
+
+        collection = db[COLLECTION_NAME]
+        _ = db.list_collection_names()
+
+        data = [
+            {"name": "Amy", "address": "Apple st 652"},
+            {"name": "Hannah", "address": "Mountain 21"},
+            {"name": "Michael", "address": "Valley 345"},
+            {"name": "Sandy", "address": "Ocean blvd 2"},
+            {"name": "Betty", "address": "Green Grass 1"},
+            {"name": "Richard", "address": "Sky st 331"},
+            {"name": "Susan", "address": "One way 98"},
+            {"name": "Vicky", "address": "Yellow Garden 2"},
+            {"name": "Ben", "address": "Park Lane 38"},
+            {"name": "William", "address": "Central st 954"},
+            {"name": "Chuck", "address": "Main Road 989"},
+            {"name": "Viola", "address": "Sideway 1633"},
+        ]
+
+        ids = collection.insert_many(data)
+
+        for id in ids.inserted_ids:
+            x = collection.find_one({"_id": id})
+            self.assertEqual(x["_id"], id)
diff --git a/installers/charm/mongodb-k8s/tests/bundles/mongodb-ha.yaml b/installers/charm/mongodb-k8s/tests/bundles/mongodb-ha.yaml
new file mode 100644 (file)
index 0000000..d08352b
--- /dev/null
@@ -0,0 +1,32 @@
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+bundle: kubernetes
+applications:
+  mongodb-k8s:
+    charm: '../../release/'
+    scale: 2
+    options:
+      enable-sidecar: true
+      namespace: mongo-ha
+    series: kubernetes
+    storage:
+      database: 50M
diff --git a/installers/charm/mongodb-k8s/tests/bundles/mongodb.yaml b/installers/charm/mongodb-k8s/tests/bundles/mongodb.yaml
new file mode 100644 (file)
index 0000000..0f2cb1a
--- /dev/null
@@ -0,0 +1,29 @@
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+bundle: kubernetes
+applications:
+  mongodb-k8s:
+    charm: '../../release/'
+    scale: 1
+    series: kubernetes
+    storage:
+      database: 50M
diff --git a/installers/charm/mongodb-k8s/tests/tests.yaml b/installers/charm/mongodb-k8s/tests/tests.yaml
new file mode 100644 (file)
index 0000000..f9a5607
--- /dev/null
@@ -0,0 +1,27 @@
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+gate_bundles:
+  - mongodb
+smoke_bundles:
+  - mongodb
+tests:
+  - tests.basic_deployment.BasicDeployment
diff --git a/installers/charm/mongodb-k8s/tox.ini b/installers/charm/mongodb-k8s/tox.ini
new file mode 100644 (file)
index 0000000..354632f
--- /dev/null
@@ -0,0 +1,91 @@
+# Copyright 2021 Canonical Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: legal@canonical.com
+#
+# To get in touch with the maintainers, please contact:
+# osm-charmers@lists.launchpad.net
+##
+
+[tox]
+envlist = pep8
+skipsdist = True
+
+[testenv]
+setenv = VIRTUAL_ENV={envdir}
+         PYTHONHASHSEED=0
+whitelist_externals = juju
+passenv = HOME TERM CS_API_* OS_* AMULET_*
+deps = -r{toxinidir}/test-requirements.txt
+install_command =
+  pip install {opts} {packages}
+
+[testenv:build]
+basepython = python3
+passenv=HTTP_PROXY HTTPS_PROXY NO_PROXY
+setenv = CHARM_LAYERS_DIR = /tmp
+         CHARM_INTERFACES_DIR = /tmp/canonical-osm/charms/interfaces/
+whitelist_externals = git
+                      charm
+                      rm
+                      mv
+commands =
+    rm -rf /tmp/canonical-osm /tmp/osm-common
+    rm -rf release/
+    git clone https://git.launchpad.net/canonical-osm /tmp/canonical-osm
+    git clone https://git.launchpad.net/charm-osm-common /tmp/osm-common
+    git clone https://git.launchpad.net/interface-mongodb /tmp/canonical-osm/charms/interfaces/mongodb
+    charm build . --build-dir /tmp
+    mv /tmp/mongodb-k8s/ release/
+
+[testenv:black]
+basepython = python3
+deps =
+    black
+    yamllint
+    flake8
+commands =
+    black --check --diff .
+    yamllint .
+    flake8 reactive/ --max-line-length=88
+    flake8 tests/ --max-line-length=88
+
+[testenv:pep8]
+basepython = python3
+deps=charm-tools
+commands = charm-proof
+
+[testenv:func-noop]
+basepython = python3
+commands =
+    true
+
+[testenv:func]
+basepython = python3
+commands =
+    functest-run-suite
+    functest-prepare -m mongo-ha
+    juju switch mongo-ha
+    functest-deploy -m mongo-ha -b ./tests/bundles/mongodb-ha.yaml
+    ; functest-test -m mongo-ha
+    functest-destroy -m mongo-ha
+
+
+[testenv:func-smoke]
+basepython = python3
+commands = functest-run-suite --keep-model --smoke
+
+[testenv:venv]
+commands = {posargs}