odoo-saas-kubernetes/kk_odoo_saas/utils/deployment.py

168 lines
6.7 KiB
Python
Executable File

from kubernetes import client
from odoo.addons.smile_log.tools import SmileDBLogger
from odoo.exceptions import UserError, ValidationError
import logging
_logger = logging.getLogger(__name__)
def create_deployment(meta_data, specs, namespace="default", self=False):
# Deployment
_logger = SmileDBLogger(self._cr.dbname, self._name, self.id, self._uid)
deployment = client.V1Deployment(
api_version="apps/v1",
kind="Deployment",
metadata=meta_data,
spec=specs)
k8s_apps_v1 = client.AppsV1Api()
try:
resp = k8s_apps_v1.create_namespaced_deployment(
body=deployment, namespace=namespace)
_logger.info("Deployment created. name='%s'" % resp.metadata.name)
except client.exceptions.ApiException as e:
_logger.error(str(e))
def create_docker_repo_secret(app_name, namespace="default", self=False):
_logger = SmileDBLogger(self._cr.dbname, self._name, self.id, self._uid)
k8s_apps_v1 = client.CoreV1Api()
secret = client.V1Secret(
metadata=client.V1ObjectMeta(
name=app_name+'-dkr-registry-key',
labels={
"app": app_name,
"tier": "backend"
}
),
data={
'.dockerconfigjson': self.docker_image.b64_dkr_config
},
type='kubernetes.io/dockerconfigjson',
)
try:
resp = k8s_apps_v1.create_namespaced_secret(
body=secret, namespace=namespace)
_logger.info("Secret created. name='%s'" % resp.metadata.name)
return True
except client.exceptions.ApiException as e:
_logger.error(str(e))
return False
def delete_docker_repo_secret(app_name, namespace="default", self=False):
_logger = SmileDBLogger(self._cr.dbname, self._name, self.id, self._uid)
k8s_apps_v1 = client.CoreV1Api()
try:
resp = k8s_apps_v1.delete_namespaced_secret(app_name+'-dkr-registry-key', namespace=namespace)
_logger.info(str(resp))
return True
except client.exceptions.ApiException as e:
_logger.error(str(e))
return False
def create_odoo_deployment(app_name, namespace="default", self=False):
image = 'odoo:15.0'
res_limits = {'ephemeral-storage': '1Gi'}
image_pull_secrets = []
if self.is_custom_image and self.docker_image:
image = "{0}:{1}".format(self.docker_image.name, self.docker_image.tag)
if self.docker_image.is_pvt_dkr_repo and self.docker_image.b64_dkr_config:
if create_docker_repo_secret(app_name, namespace, self):
sec_name = app_name+"-dkr-registry-key"
image_pull_secrets.append(client.V1LocalObjectReference(name=sec_name))
meta_data = client.V1ObjectMeta(name=app_name + "-odoo-deployment",
labels={"app": app_name})
args_odoo = ['--database=' + self.sub_domain_name]
# args_odoo = []
if self.demo_data:
args_odoo.append('--without-demo=False')
else:
args_odoo.append('--without-demo=True')
if self.module_ids:
module_names = ''
for module in self.module_ids:
module_names = module_names + module.name + ','
args_odoo.append("--init={0}".format(module_names))
if self.db_server_id:
_logger.critical('Cant deploy app, PG username or password cant find')
UserError("Cant deploy app, PG username or password cant find")
limits = client.V1ResourceRequirements(limits=res_limits)
tolerations = []
node_selector = {}
if self and self.is_dedicated_node and self.node_id:
# tolerations = [client.V1Toleration(effect='NoSchedule', key=self.node_key, value=self.node_value, operator='Equal')]
# specific for aws clusters
node_selector['kubernetes.io/hostname'] = self.node_id.name
odoo_container = client.V1Container(
name="odoo",
image=image,
env=[
client.V1EnvVar(name="HOST", value=self.db_server_id.server_url),
client.V1EnvVar(name="USER", value=self.db_server_id.master_username),
client.V1EnvVar(name="PASSWORD", value=self.db_server_id.master_pass),
client.V1EnvVar(name="PORT", value=self.db_server_id.server_port),
client.V1EnvVar(name="ODOO_HTTP_SOCKET_TIMEOUT", value="100"),
],
ports=[client.V1ContainerPort(container_port=8069, name="odoo-port"),
client.V1ContainerPort(container_port=8072, name="longpolling")],
args=args_odoo,
image_pull_policy='Always',
# command=['chown', '-R', '101:101', '/mnt/extra-addons'],
resources=limits,
# comment following line, if you want to run as odoo user
# security_context=client.V1SecurityContext(run_as_user=0, run_as_group=0),
volume_mounts=[client.V1VolumeMount(name=app_name + "-odoo-web-pv-storage", mount_path="/var/lib/odoo/")]
)
# pod Volume Claim
volume_claim = client.V1PersistentVolumeClaimVolumeSource(claim_name=app_name + "-odoo-web-pv-claim")
# pod volume
volume = client.V1Volume(name=app_name + "-odoo-web-pv-storage", persistent_volume_claim=volume_claim)
# Strategy
strategy = client.V1DeploymentStrategy(type="Recreate")
# Template
# for running as a odoo user changes instead of stash
spec = client.V1PodSpec(containers=[odoo_container], volumes=[volume], image_pull_secrets=image_pull_secrets,
security_context=client.V1PodSecurityContext(run_as_group=101, run_as_user=101,
fs_group=101, fs_group_change_policy='Always'),
node_selector=node_selector)
template = client.V1PodTemplateSpec(
metadata=client.V1ObjectMeta(labels={"app": app_name, "tier": "backend"}),
spec=spec
)
selector = client.V1LabelSelector(match_labels={"app": app_name, "tier": "backend"})
# Spec
specs = client.V1DeploymentSpec(
replicas=1,
strategy=strategy,
selector=selector,
template=template,
)
create_deployment(meta_data, specs, namespace, self=self)
def delete_odoo_deployment(app_name, namespace="default", self=False):
_logger = SmileDBLogger(self._cr.dbname, self._name, self.id, self._uid)
dep_name = app_name + "-odoo-deployment"
core_v1_api = client.AppsV1Api()
try:
deployment = core_v1_api.delete_namespaced_deployment(name=dep_name, namespace=namespace)
if self.is_custom_image and self.docker_image:
if self.docker_image.is_pvt_dkr_repo and self.docker_image.b64_dkr_config:
delete_docker_repo_secret(app_name, namespace, self)
_logger.info(str(deployment))
except client.exceptions.ApiException as e:
_logger.error(str(e))