blob: bb68d4959ca06b5391047da235b993f86aa37c1f [file] [log] [blame]
import os
import tomli
from schematics import types
from schematics.exceptions import ValidationError
from atmosphere import utils
from atmosphere.models import base
CONFIG_FILE = os.environ.get("ATMOSPHERE_CONFIG", "/etc/atmosphere/config.toml")
class AcmeIssuerSolverConfig(base.Model):
type = types.StringType(
choices=("http", "rfc2136", "route53"), default="http", required=True
)
@classmethod
def _claim_polymorphic(cls, data):
return data.get("type", cls.type.default) == cls.TYPE
class HttpAcmeIssuerSolverConfig(AcmeIssuerSolverConfig):
TYPE = "http"
class Rfc2136AcmeIssuerSolverConfig(AcmeIssuerSolverConfig):
TYPE = "rfc2136"
nameserver = types.StringType(required=True)
tsig_algorithm = types.StringType(required=True)
tsig_key_name = types.StringType(required=True)
tsig_secret = types.StringType(required=True)
class Route53AcmeIssuerSolverConfig(AcmeIssuerSolverConfig):
TYPE = "route53"
region = types.StringType(default="global", required=True)
hosted_zone_id = types.StringType(required=True)
access_key_id = types.StringType(required=True)
secret_access_key = types.StringType(required=True)
class Issuer(base.Model):
type = types.StringType(
choices=("acme", "ca", "self-signed"), default="acme", required=True
)
@classmethod
def _claim_polymorphic(cls, data):
return data.get("type", cls.type.default) == cls.TYPE
class AcmeIssuerConfig(Issuer):
TYPE = "acme"
email = types.StringType(required=True)
server = types.URLType(default="https://acme-v02.api.letsencrypt.org/directory")
solver = types.PolyModelType(
[
HttpAcmeIssuerSolverConfig,
Rfc2136AcmeIssuerSolverConfig,
Route53AcmeIssuerSolverConfig,
],
default=HttpAcmeIssuerSolverConfig(),
required=True,
)
class CaIssuerConfig(Issuer):
TYPE = "ca"
certificate = types.StringType(required=True)
private_key = types.StringType(required=True)
class SelfSignedIssuerConfig(Issuer):
TYPE = "self-signed"
class ChartConfig(base.Model):
enabled = types.BooleanType(default=True, required=True)
overrides = types.DictType(types.BaseType(), default={})
class KubePrometheusStackChartConfig(ChartConfig):
namespace = types.StringType(default="monitoring", required=True)
class MemcachedImagesConfig(base.Model):
memcached = types.StringType(
default=utils.get_image_ref_using_legacy_image_repository("memcached").string()
)
exporter = types.StringType(
default=utils.get_image_ref_using_legacy_image_repository(
"prometheus_memcached_exporter"
).string()
)
class MemcachedChartConfig(ChartConfig):
namespace = types.StringType(default="openstack", required=True)
secret_key = types.StringType(required=True)
images = types.ModelType(MemcachedImagesConfig, default=MemcachedImagesConfig())
class IngressNginxChartConfig(ChartConfig):
namespace = types.StringType(default="openstack", required=True)
class OpsGenieConfig(base.Model):
enabled = types.BooleanType(default=False, required=True)
api_key = types.StringType()
heartbeat = types.StringType()
def validate_api_key(self, data, value):
if data["enabled"] and not value:
raise ValidationError(types.BaseType.MESSAGES["required"])
return value
def validate_heartbeat(self, data, value):
if data["enabled"] and not value:
raise ValidationError(types.BaseType.MESSAGES["required"])
return value
class Config(base.Model):
image_repository = types.StringType()
kube_prometheus_stack = types.ModelType(
KubePrometheusStackChartConfig, default=KubePrometheusStackChartConfig()
)
ingress_nginx = types.ModelType(
IngressNginxChartConfig, default=IngressNginxChartConfig()
)
memcached = types.ModelType(
MemcachedChartConfig, default=MemcachedChartConfig(), required=True
)
issuer = types.PolyModelType(
[AcmeIssuerConfig, CaIssuerConfig, SelfSignedIssuerConfig],
default=AcmeIssuerConfig(),
required=True,
)
opsgenie = types.ModelType(OpsGenieConfig, default=OpsGenieConfig())
@classmethod
def from_toml(cls, data, validate=True):
c = cls(data, validate=validate)
if validate:
c.validate()
return c
@classmethod
def from_file(cls, path=CONFIG_FILE):
with open(path, "rb") as fd:
data = tomli.load(fd)
return cls.from_toml(data)
@classmethod
def from_string(cls, data: str, validate=True):
data = tomli.loads(data)
return cls.from_toml(data, validate)