promenade/promenade/config.py

96 lines
2.3 KiB
Python

from . import logging
from operator import attrgetter, itemgetter
import itertools
import yaml
__all__ = ['Configuration', 'Document', 'load']
LOG = logging.getLogger(__name__)
def load(f):
return Configuration(list(map(Document, yaml.load_all(f))))
class Document:
KEYS = {
'apiVersion',
'metadata',
'kind',
'spec',
}
SUPPORTED_KINDS = {
'Certificate',
'CertificateAuthority',
'CertificateAuthorityKey',
'CertificateKey',
'Cluster',
'Etcd',
'Masters',
'Network',
'Node',
'PrivateKey',
'PublicKey',
}
def __init__(self, data):
assert set(data.keys()) == self.KEYS
assert data['apiVersion'] == 'promenade/v1'
assert data['kind'] in self.SUPPORTED_KINDS
self.data = data
@property
def kind(self):
return self.data['kind']
@property
def target(self):
return self.metadata.get('target')
@property
def metadata(self):
return self.data['metadata']
def __getitem__(self, key):
return self.data['spec'][key]
class Configuration:
def __init__(self, documents):
self.documents = sorted(documents, key=attrgetter('kind', 'target'))
def __getitem__(self, key):
results = [d for d in self.documents if d.kind == key]
if len(results) < 1:
raise KeyError
elif len(results) > 1:
raise KeyError('Too many results.')
else:
return results[0]
def iterate(self, *, kind=None, target=None):
if target:
docs = self._iterate_with_target(target)
else:
docs = self.documents
for document in docs:
if not kind or document.kind == kind:
yield document
def _iterate_with_target(self, target):
for document in self.documents:
if document.target == target or document.target == 'all':
yield document
def write(self, path):
with open(path, 'w') as f:
yaml.dump_all(map(attrgetter('data'), self.documents),
default_flow_style=False,
explicit_start=True,
indent=2,
stream=f)