zuul-operator/zuul_operator/pxc.py

108 lines
3.9 KiB
Python

# Copyright 2021 Acme Gating, LLC
#
# 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.
import time
import base64
import pykube
from . import objects
from . import utils
class PXC:
def __init__(self, api, namespace, logger):
self.api = api
self.namespace = namespace
self.log = logger
def is_installed(self):
kind = objects.get_object('apiextensions.k8s.io/v1beta1',
'CustomResourceDefinition')
try:
kind.objects(self.api).\
get(name="perconaxtradbclusters.pxc.percona.com")
except pykube.exceptions.ObjectDoesNotExist:
return False
return True
def create_operator(self):
# We don't adopt this so that the operator can continue to run
# after the pxc cr is deleted; if we did adopt it, then when
# the zuul cr is deleted, the operator would be immediately
# deleted and the cluster orphaned. Basically, we get to
# choose whether to orphan the cluster or the operator, and
# the operator seems like the better choice.
utils.apply_file(self.api, 'pxc-crd.yaml', _adopt=False)
utils.apply_file(self.api, 'pxc-operator.yaml',
namespace=self.namespace, _adopt=False)
def create_cluster(self, small):
kw = {'namespace': self.namespace}
kw['anti_affinity_key'] = small and 'none' or 'kubernetes.io/hostname'
kw['allow_unsafe'] = small and True or False
utils.apply_file(self.api, 'pxc-cluster.yaml', **kw)
def wait_for_cluster(self):
while True:
count = 0
for obj in objects.Pod.objects(self.api).filter(
namespace=self.namespace,
selector={'app.kubernetes.io/instance': 'db-cluster',
'app.kubernetes.io/component': 'pxc',
'app.kubernetes.io/name':
'percona-xtradb-cluster'}):
if obj.obj['status']['phase'] == 'Running':
count += 1
if count == 3:
self.log.info("Database cluster is running")
return
else:
self.log.info(f"Waiting for database cluster: {count}/3")
time.sleep(10)
def get_root_password(self):
obj = objects.Secret.objects(self.api).\
filter(namespace=self.namespace).\
get(name="db-cluster-secrets")
pw = base64.b64decode(obj.obj['data']['root']).decode('utf8')
return pw
def create_database(self):
root_pw = self.get_root_password()
zuul_pw = utils.generate_password()
utils.apply_file(self.api, 'pxc-create-db.yaml',
namespace=self.namespace,
root_password=root_pw,
zuul_password=zuul_pw)
while True:
obj = objects.Job.objects(self.api).\
filter(namespace=self.namespace).\
get(name='create-database')
if obj.obj['status'].get('succeeded'):
break
time.sleep(2)
obj.delete(propagation_policy="Foreground")
dburi = f'mysql+pymysql://zuul:{zuul_pw}@db-cluster-haproxy/zuul'
utils.update_secret(self.api, self.namespace, 'zuul-db',
string_data={'dburi': dburi})
return dburi