Revert "Feature 11071: Modular OSM installation. Remove charms, juju and lxd"
This reverts commit a0f0d8ef4f2aa0dd227ecb651002490b66498bab.
Change-Id: I92394e4074dad4e457c107c58e4ebc17d507f8b2
Signed-off-by: garciadeblas <gerardo.garciadeblas@telefonica.com>
diff --git a/installers/charm/mariadb-k8s/.gitignore b/installers/charm/mariadb-k8s/.gitignore
new file mode 100644
index 0000000..712eb96
--- /dev/null
+++ b/installers/charm/mariadb-k8s/.gitignore
@@ -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/mariadb-k8s/.yamllint.yaml b/installers/charm/mariadb-k8s/.yamllint.yaml
new file mode 100644
index 0000000..567eb5f
--- /dev/null
+++ b/installers/charm/mariadb-k8s/.yamllint.yaml
@@ -0,0 +1,33 @@
+# 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
+
+yaml-files:
+ - '*.yaml'
+ - '*.yml'
+ - '.yamllint'
+ignore: |
+ reactive/
+ .tox
+ release/
diff --git a/installers/charm/mariadb-k8s/README.md b/installers/charm/mariadb-k8s/README.md
new file mode 100755
index 0000000..5c89de1
--- /dev/null
+++ b/installers/charm/mariadb-k8s/README.md
@@ -0,0 +1,78 @@
+<!-- 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 -->
+
+# MariaDB Operator
+
+A Juju charm deploying and managing MariaDB on Kubernetes.
+
+## Overview
+
+MariaDB turns data into structured information in a wide array of
+applications, ranging from banking to websites. Originally designed as
+enhanced, drop-in replacement for MySQL, MariaDB is used because it is fast,
+scalable and robust, with a rich ecosystem of storage engines, plugins and
+many other tools make it very versatile for a wide variety of use cases.
+
+MariaDB is developed as open source software and as a relational database it
+provides an SQL interface for accessing data. The latest versions of MariaDB
+also include GIS and JSON features.
+
+More information can be found in [the MariaDB Knowledge Base](https://mariadb.com/kb/en/documentation/).
+
+## Usage
+
+For details on using Kubernetes with Juju [see here](https://juju.is/docs/kubernetes), and for
+details on using Juju with MicroK8s for easy local testing [see here](https://juju.is/docs/microk8s-cloud).
+
+To deploy the charm into a Juju Kubernetes model:
+
+ juju deploy cs:~charmed-osm/mariadb
+
+The charm can then be easily related to an application that supports the mysql
+relation, such as:
+
+ juju deploy cs:~charmed-osm/keystone
+ juju relate keystone mariadb-k8s
+
+Once the "Workload" status of both mariadb-k8s and keystone is "active", using
+the "Application" IP of keystone (from `juju status`):
+
+ # Change as appropriate for you juju model
+ KEYSTONE_APPLICATION_IP=10.152.183.222
+ curl -i -H "Content-Type: application/json" -d '
+ { "auth": {
+ "identity": {
+ "methods": ["password"],
+ "password": {
+ "user": {
+ "name": "admin",
+ "domain": { "id": "default" },
+ "password": "admin"
+ }
+ }
+ }
+ }
+ ' "http://${KEYSTONE_APPLICATION_IP}:5000/v3/auth/tokens" ; echo
+
+This will create a token that you could use to query Keystone.
+
+---
+
+For more details, [see here](https://charmhub.io/mariadb/docs/).
diff --git a/installers/charm/mariadb-k8s/actions.yaml b/installers/charm/mariadb-k8s/actions.yaml
new file mode 100644
index 0000000..0b33b6a
--- /dev/null
+++ b/installers/charm/mariadb-k8s/actions.yaml
@@ -0,0 +1,42 @@
+# 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: "Perform a backup"
+ params:
+ path:
+ description: "Path for the backup inside the unit"
+ type: string
+ default: "/var/lib/mysql"
+restore:
+ description: "Restore from a backup"
+ params:
+ path:
+ description: "Path for the backup inside the unit"
+ type: string
+ default: "/var/lib/mysql"
+remove-backup:
+ description: "Remove backup from unit"
+ params:
+ path:
+ description: "Path for the backup inside the unit"
+ type: string
+ default: "/var/lib/mysql"
diff --git a/installers/charm/mariadb-k8s/actions/backup b/installers/charm/mariadb-k8s/actions/backup
new file mode 100755
index 0000000..7bfb5e4
--- /dev/null
+++ b/installers/charm/mariadb-k8s/actions/backup
@@ -0,0 +1,30 @@
+#!/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`
+mkdir -p $DB_BACKUP_PATH
+ROOT_PASSWORD=`config-get root_password`
+mysqldump -u root -p$ROOT_PASSWORD --single-transaction --all-databases | gzip > $DB_BACKUP_PATH/backup.sql.gz || action-fail "Backup failed"
+action-set copy.cmd="kubectl cp $JUJU_MODEL_NAME/$HOSTNAME:$DB_BACKUP_PATH/backup.sql.gz backup.sql.gz"
+action-set restore.cmd="kubectl cp backup.sql.gz $JUJU_MODEL_NAME/$HOSTNAME:$DB_BACKUP_PATH/backup.sql.gz"
+action-set restore.juju="juju run-action $JUJU_UNIT_NAME restore --wait"
+
diff --git a/installers/charm/mariadb-k8s/actions/remove-backup b/installers/charm/mariadb-k8s/actions/remove-backup
new file mode 100755
index 0000000..f304333
--- /dev/null
+++ b/installers/charm/mariadb-k8s/actions/remove-backup
@@ -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.sql.gz || exit
+echo Backup successfully removed!
diff --git a/installers/charm/mariadb-k8s/actions/restore b/installers/charm/mariadb-k8s/actions/restore
new file mode 100755
index 0000000..768e68e
--- /dev/null
+++ b/installers/charm/mariadb-k8s/actions/restore
@@ -0,0 +1,26 @@
+#!/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`
+ROOT_PASSWORD=`config-get root_password`
+gunzip -c $DB_BACKUP_PATH/backup.sql.gz | mysql -uroot -p$ROOT_PASSWORD || action-fail "Restore failed"
+action-set message="Backup restored successfully"
\ No newline at end of file
diff --git a/installers/charm/mariadb-k8s/charmcraft.yaml b/installers/charm/mariadb-k8s/charmcraft.yaml
new file mode 100644
index 0000000..69a510c
--- /dev/null
+++ b/installers/charm/mariadb-k8s/charmcraft.yaml
@@ -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
+##
+
+type: "charm"
+bases:
+ - build-on:
+ - name: "ubuntu"
+ channel: "20.04"
+ run-on:
+ - name: "ubuntu"
+ channel: "20.04"
+parts:
+ charm:
+ source: .
+ plugin: reactive
+ build-snaps: [charm]
diff --git a/installers/charm/mariadb-k8s/config.yaml b/installers/charm/mariadb-k8s/config.yaml
new file mode 100755
index 0000000..8a606a4
--- /dev/null
+++ b/installers/charm/mariadb-k8s/config.yaml
@@ -0,0 +1,66 @@
+# 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:
+ user:
+ type: string
+ description: 'The database user name.'
+ default: 'mysql'
+ password:
+ type: string
+ description: 'The database user password.'
+ default: 'password'
+ database:
+ type: string
+ description: 'The database name.'
+ default: 'database'
+ root_password:
+ type: string
+ description: 'The database root password.'
+ default: 'root'
+ mysql_port:
+ type: string
+ description: 'The mysql port'
+ default: '3306'
+ query-cache-type:
+ default: "OFF"
+ type: string
+ description: "Query cache is usually a good idea, \
+ but can hurt concurrency. \
+ Valid values are \"OFF\", \"ON\", or \"DEMAND\"."
+ query-cache-size:
+ default: !!int "0"
+ type: int
+ description: "Override the computed version from dataset-size. \
+ Still works if query-cache-type is \"OFF\" since sessions \
+ can override the cache type setting on their own."
+ ha-mode:
+ type: boolean
+ description: Indicates if the charm should have the capabilities to scale
+ default: false
+ image:
+ type: string
+ description: OCI image
+ default: rocks.canonical.com:443/mariadb/server:10.3
+ ha-image:
+ type: string
+ description: OCI image
+ default: rocks.canonical.com:443/canonicalosm/galera-mysql:latest
diff --git a/installers/charm/mariadb-k8s/icon.svg b/installers/charm/mariadb-k8s/icon.svg
new file mode 100644
index 0000000..69b42ee
--- /dev/null
+++ b/installers/charm/mariadb-k8s/icon.svg
@@ -0,0 +1,345 @@
+<?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"
+ version="1.1"
+ id="svg3767"
+ width="640"
+ height="578"
+ viewBox="0 0 640 578"
+ sodipodi:docname="icon.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata3773">
+ <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></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3771" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="2560"
+ inkscape:window-height="1376"
+ id="namedview3769"
+ showgrid="false"
+ inkscape:zoom="2.100346"
+ inkscape:cx="320"
+ inkscape:cy="289"
+ inkscape:window-x="0"
+ inkscape:window-y="27"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg3767" />
+ <image
+ width="640"
+ height="578"
+ preserveAspectRatio="none"
+ xlink:href="data:image/png;base64,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
+PAAAAABJRU5ErkJggg==
+"
+ id="image3775"
+ x="0"
+ y="0" />
+</svg>
diff --git a/installers/charm/mariadb-k8s/layer.yaml b/installers/charm/mariadb-k8s/layer.yaml
new file mode 100644
index 0000000..f9b5dd9
--- /dev/null
+++ b/installers/charm/mariadb-k8s/layer.yaml
@@ -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:juju-relation-mysql'
+
+repo: https://github.com/wallyworld/caas.git
diff --git a/installers/charm/mariadb-k8s/metadata.yaml b/installers/charm/mariadb-k8s/metadata.yaml
new file mode 100755
index 0000000..a802115
--- /dev/null
+++ b/installers/charm/mariadb-k8s/metadata.yaml
@@ -0,0 +1,46 @@
+# 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: osm-mariadb
+summary: MariaDB is a popular database server made by the developers of MySQL.
+# docs: https://discourse.charmhub.io/t/mariadb-documentation-overview/4116
+maintainers:
+ - OSM Charmers <osm-charmers@lists.launchpad.net>
+description: |
+ MariaDB Server is one of the most popular database servers in the world.
+ It's made by the original developers of MySQL and guaranteed to stay open
+ source. Notable users include Wikipedia, WordPress.com and Google.
+ https://mariadb.org/
+tags:
+ - database
+ - openstack
+provides:
+ mysql:
+ interface: mysql
+series:
+ - kubernetes
+storage:
+ database:
+ type: filesystem
+ location: /var/lib/mysql
+deployment:
+ type: stateful
+ service: cluster
diff --git a/installers/charm/mariadb-k8s/reactive/osm_mariadb.py b/installers/charm/mariadb-k8s/reactive/osm_mariadb.py
new file mode 100644
index 0000000..4eedcfb
--- /dev/null
+++ b/installers/charm/mariadb-k8s/reactive/osm_mariadb.py
@@ -0,0 +1,141 @@
+# 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 when, when_not, hook
+from charms.reactive import endpoint_from_flag
+from charms.reactive.flags import set_flag, get_state, clear_flag
+
+from charmhelpers.core.hookenv import (
+ log,
+ metadata,
+ config,
+ application_name,
+)
+from charms import layer
+from charms.osm.k8s import is_pod_up, get_service_ip
+
+
+@hook("upgrade-charm")
+@when("leadership.is_leader")
+def upgrade():
+ clear_flag("mariadb-k8s.configured")
+
+
+@when("config.changed")
+@when("leadership.is_leader")
+def restart():
+ clear_flag("mariadb-k8s.configured")
+
+
+@when_not("mariadb-k8s.configured")
+@when("leadership.is_leader")
+def configure():
+ layer.status.maintenance("Configuring mariadb-k8s container")
+
+ spec = make_pod_spec()
+ log("set pod spec:\n{}".format(spec))
+ pod_spec_set(spec)
+
+ set_flag("mariadb-k8s.configured")
+
+
+@when("mariadb-k8s.configured")
+def set_mariadb_active():
+ layer.status.active("ready")
+
+
+@when_not("leadership.is_leader")
+def non_leaders_active():
+ layer.status.active("ready")
+
+
+@when("mariadb-k8s.configured", "mysql.database.requested")
+def provide_database():
+ mysql = endpoint_from_flag("mysql.database.requested")
+
+ if not is_pod_up("mysql"):
+ log("The pod is not ready.")
+ return
+
+ for request, application in mysql.database_requests().items():
+ try:
+
+ log("request -> {0} for app -> {1}".format(request, application))
+ user = get_state("user")
+ password = get_state("password")
+ database_name = get_state("database")
+ root_password = get_state("root_password")
+
+ log("db params: {0}:{1}@{2}".format(user, password, database_name))
+
+ service_ip = get_service_ip("mysql")
+ if service_ip:
+ mysql.provide_database(
+ request_id=request,
+ host=service_ip,
+ port=3306,
+ database_name=database_name,
+ user=user,
+ password=password,
+ root_password=root_password,
+ )
+ mysql.mark_complete()
+ except Exception as e:
+ log("Exception while providing database: {}".format(e))
+
+
+def make_pod_spec():
+ """Make pod specification for Kubernetes
+
+ Returns:
+ pod_spec: Pod specification for Kubernetes
+ """
+ if config().get("ha-mode"):
+ with open("reactive/spec_template_ha.yaml") as spec_file:
+ pod_spec_template = spec_file.read()
+ image = config().get("ha-image")
+ else:
+ with open("reactive/spec_template.yaml") as spec_file:
+ pod_spec_template = spec_file.read()
+ image = config().get("image")
+
+ md = metadata()
+ cfg = config()
+
+ user = cfg.get("user")
+ password = cfg.get("password")
+ database = cfg.get("database")
+ root_password = cfg.get("root_password")
+ app_name = application_name()
+
+ set_flag("user", user)
+ set_flag("password", password)
+ set_flag("database", database)
+ set_flag("root_password", root_password)
+
+ data = {
+ "name": md.get("name"),
+ "docker_image": image,
+ "application_name": app_name,
+ }
+ data.update(cfg)
+ return pod_spec_template % data
diff --git a/installers/charm/mariadb-k8s/reactive/spec_template.yaml b/installers/charm/mariadb-k8s/reactive/spec_template.yaml
new file mode 100644
index 0000000..0a1facc
--- /dev/null
+++ b/installers/charm/mariadb-k8s/reactive/spec_template.yaml
@@ -0,0 +1,51 @@
+# 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
+ ports:
+ - containerPort: %(mysql_port)s
+ protocol: TCP
+ name: main
+ config:
+ MARIADB_ROOT_PASSWORD: %(root_password)s
+ MARIADB_USER: %(user)s
+ MARIADB_PASSWORD: %(password)s
+ MARIADB_DATABASE: %(database)s
+ kubernetes:
+ readinessProbe:
+ tcpSocket:
+ port: %(mysql_port)s
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ timeoutSeconds: 5
+ successThreshold: 1
+ failureThreshold: 3
+ livenessProbe:
+ tcpSocket:
+ port: %(mysql_port)s
+ initialDelaySeconds: 120
+ periodSeconds: 10
+ timeoutSeconds: 5
+ successThreshold: 1
+ failureThreshold: 3
diff --git a/installers/charm/mariadb-k8s/reactive/spec_template_ha.yaml b/installers/charm/mariadb-k8s/reactive/spec_template_ha.yaml
new file mode 100644
index 0000000..f5ebf20
--- /dev/null
+++ b/installers/charm/mariadb-k8s/reactive/spec_template_ha.yaml
@@ -0,0 +1,97 @@
+# 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
+service:
+ scalePolicy: serial
+ annotations:
+ service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
+containers:
+ - name: %(name)s
+ image: %(docker_image)s
+ kubernetes:
+ readinessProbe:
+ tcpSocket:
+ port: %(mysql_port)s
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ timeoutSeconds: 5
+ successThreshold: 1
+ failureThreshold: 3
+ livenessProbe:
+ exec:
+ command: ["bash", "-c", "mysql -uroot -p\"${MYSQL_ROOT_PASSWORD}\" -e 'show databases;'"]
+ initialDelaySeconds: 120
+ periodSeconds: 10
+ timeoutSeconds: 5
+ successThreshold: 1
+ failureThreshold: 3
+ ports:
+ - containerPort: %(mysql_port)s
+ protocol: TCP
+ name: main
+ - containerPort: 4444
+ name: sst
+ - containerPort: 4567
+ name: replication
+ - containerPort: 4568
+ name: ist
+ config:
+ MYSQL_ROOT_PASSWORD: %(root_password)s
+ APPLICATION_NAME: %(application_name)s
+ MYSQL_USER: %(user)s
+ MYSQL_PASSWORD: %(password)s
+ MYSQL_DATABASE: %(database)s
+ files:
+ - name: configurations
+ mountPath: /etc/mysqlconfiguration
+ files:
+ galera.cnf: |
+ [galera]
+ user = mysql
+ bind-address = 0.0.0.0
+
+ default_storage_engine = InnoDB
+ binlog_format = ROW
+ innodb_autoinc_lock_mode = 2
+ innodb_flush_log_at_trx_commit = 0
+ query_cache_size = 0
+ host_cache_size = 0
+ query_cache_type = 0
+
+ # MariaDB Galera settings
+ wsrep_on=ON
+ wsrep_provider=/usr/lib/galera/libgalera_smm.so
+ wsrep_sst_method=rsync
+
+ # Cluster settings (automatically updated)
+ wsrep_cluster_address=gcomm://
+ wsrep_cluster_name=vimdb_cluser
+ wsrep_node_address=127.0.0.1
+ mariadb.cnf: |
+ [client]
+ default-character-set = utf8
+ [mysqld]
+ character-set-server = utf8
+ collation-server = utf8_general_ci
+ plugin_load_add = feedbackx#
+ # InnoDB tuning
+ innodb_log_file_size = 50M
diff --git a/installers/charm/mariadb-k8s/test-requirements.txt b/installers/charm/mariadb-k8s/test-requirements.txt
new file mode 100644
index 0000000..04f2d76
--- /dev/null
+++ b/installers/charm/mariadb-k8s/test-requirements.txt
@@ -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
+mysql.connector
\ No newline at end of file
diff --git a/installers/charm/mariadb-k8s/tests/basic_deployment.py b/installers/charm/mariadb-k8s/tests/basic_deployment.py
new file mode 100644
index 0000000..fd6520f
--- /dev/null
+++ b/installers/charm/mariadb-k8s/tests/basic_deployment.py
@@ -0,0 +1,136 @@
+#!/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
+
+import mysql.connector as mysql
+
+# from mysql.connector import errorcode
+
+APPLICATION_NAME = "mariadb-k8s"
+UNIT_NAME = "mariadb-k8s/0"
+ROOT_USER = "root"
+ROOT_PASSWORD = "osm4u"
+USER = "mano"
+PASSWORD = "manopw"
+ACTION_SUCCESS_STATUS = "completed"
+
+
+def create_database(cnx, database_name):
+ try:
+ if not database_exists(cnx, database_name):
+ cursor = cnx.cursor()
+ cursor.execute(
+ "CREATE DATABASE {} DEFAULT CHARACTER SET 'utf8'".format(database_name)
+ )
+ return database_exists(cnx, database_name)
+ else:
+ return True
+ except mysql.Error as err:
+ print("Failed creating database {}: {}".format(database_name, err))
+
+
+def delete_database(cnx, database_name):
+ try:
+ if database_exists(cnx, database_name):
+ cursor = cnx.cursor()
+ cursor.execute("DROP DATABASE {}".format(database_name))
+ return not database_exists(cnx, database_name)
+ else:
+ return True
+ except mysql.Error as err:
+ print("Failed deleting database {}: {}".format(database_name, err))
+
+
+def database_exists(cnx, database_name):
+ try:
+ cursor = cnx.cursor()
+ cursor.execute("SHOW DATABASES")
+ databases = cursor.fetchall()
+ exists = False
+ for database in databases:
+ if database[0] == database_name:
+ exists = True
+ cursor.close()
+ return exists
+ except mysql.Error as err:
+ print("Failed deleting database {}: {}".format(database_name, err))
+ return False
+
+
+class BasicDeployment(unittest.TestCase):
+ def setUp(self):
+ super().setUp()
+ self.ip = model.get_status().applications[APPLICATION_NAME]["public-address"]
+ try:
+ self.cnx = mysql.connect(
+ user=ROOT_USER, password=ROOT_PASSWORD, host=self.ip
+ )
+ except mysql.Error as err:
+ print("Couldn't connect to mariadb-k8s : {}".format(err))
+
+ def tearDown(self):
+ super().tearDown()
+ self.cnx.close()
+
+ def test_mariadb_connection_root(self):
+ pass
+
+ def test_mariadb_connection_user(self):
+ try:
+ cnx = mysql.connect(user=USER, password=PASSWORD, host=self.ip)
+ cnx.close()
+ except mysql.Error as err:
+ print("Couldn't connect to mariadb-k8s with user creds: {}".format(err))
+
+ def test_mariadb_create_database(self):
+ created = create_database(self.cnx, "test_database")
+ self.failIf(not created)
+
+ def test_mariadb_backup_action(self, db_name="test_backup"):
+ created = create_database(self.cnx, db_name)
+ self.failIf(not created)
+ try:
+ action = model.run_action(UNIT_NAME, "backup", raise_on_failure=True)
+ self.assertEqual(action.status, ACTION_SUCCESS_STATUS)
+ except model.ActionFailed as err:
+ print("Action failed: {}".format(err))
+
+ def test_mariadb_remove_backup_action(self):
+ self.test_mariadb_backup_action(db_name="test_remove_backup")
+ try:
+ action = model.run_action(UNIT_NAME, "remove-backup", raise_on_failure=True)
+ self.assertEqual(action.status, ACTION_SUCCESS_STATUS)
+ except model.ActionFailed as err:
+ print("Action failed: {}".format(err))
+
+ def test_mariadb_restore_action(self):
+ self.test_mariadb_backup_action(db_name="test_restore")
+ deleted = delete_database(self.cnx, "test_restore")
+ self.failIf(not deleted)
+ try:
+ action = model.run_action(UNIT_NAME, "restore", raise_on_failure=True)
+ self.assertEqual(action.status, "completed")
+ self.assertTrue(database_exists(self.cnx, "test_restore"))
+ except model.ActionFailed as err:
+ print("Action failed: {}".format(err))
diff --git a/installers/charm/mariadb-k8s/tests/bundles/mariadb-ha.yaml b/installers/charm/mariadb-k8s/tests/bundles/mariadb-ha.yaml
new file mode 100644
index 0000000..7692bd5
--- /dev/null
+++ b/installers/charm/mariadb-k8s/tests/bundles/mariadb-ha.yaml
@@ -0,0 +1,39 @@
+# 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:
+ mariadb-k8s:
+ charm: '../../release/'
+ scale: 2
+ options:
+ password: manopw
+ root_password: osm4u
+ user: mano
+ database: database
+ mysql_port: "3306"
+ query-cache-type: "OFF"
+ query-cache-size: 0
+ ha-mode: true
+ image: 'rocks.canonical.com:443/canonicalosm/galera-mysql:latest'
+ series: kubernetes
+ storage:
+ database: 50M
diff --git a/installers/charm/mariadb-k8s/tests/bundles/mariadb.yaml b/installers/charm/mariadb-k8s/tests/bundles/mariadb.yaml
new file mode 100644
index 0000000..e3e3aa3
--- /dev/null
+++ b/installers/charm/mariadb-k8s/tests/bundles/mariadb.yaml
@@ -0,0 +1,38 @@
+# 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:
+ mariadb-k8s:
+ charm: '../../release/'
+ scale: 1
+ options:
+ password: manopw
+ root_password: osm4u
+ user: mano
+ database: database
+ mysql_port: "3306"
+ query-cache-type: "OFF"
+ query-cache-size: 0
+ ha-mode: false
+ series: kubernetes
+ storage:
+ database: 50M
diff --git a/installers/charm/mariadb-k8s/tests/tests.yaml b/installers/charm/mariadb-k8s/tests/tests.yaml
new file mode 100644
index 0000000..df2b59c
--- /dev/null
+++ b/installers/charm/mariadb-k8s/tests/tests.yaml
@@ -0,0 +1,28 @@
+# 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:
+ - mariadb
+ - mariadb-ha
+smoke_bundles:
+ - mariadb
+tests:
+ - tests.basic_deployment.BasicDeployment
diff --git a/installers/charm/mariadb-k8s/tox.ini b/installers/charm/mariadb-k8s/tox.ini
new file mode 100644
index 0000000..28d60be
--- /dev/null
+++ b/installers/charm/mariadb-k8s/tox.ini
@@ -0,0 +1,84 @@
+# 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
+ charm build . --build-dir /tmp
+ mv /tmp/mariadb-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
+
+
+[testenv:func-smoke]
+basepython = python3
+commands = functest-run-suite --keep-model --smoke
+
+[testenv:venv]
+commands = {posargs}