yaml.add_representer(IngressSpec, ServiceSpec.yaml_representer)
+class InitContainerSpec(object):
+ """An init container is not a service that lives on its own, but rather
+ is used to run and exit prior to a service container starting in order
+ to help initialize some aspect of the container environment.
+ For example: a command to pre-populate a DB file with expected values
+ before the server starts.
+ """
+
+ _basic_fields = [
+ 'image',
+ 'entrypoint',
+ 'volume_mounts',
+ 'envs',
+ 'privileged',
+ ]
+ _fields = _basic_fields + ['entrypoint_args']
+
+ def __init__(
+ self,
+ image: Optional[str] = None,
+ entrypoint: Optional[str] = None,
+ entrypoint_args: Optional[GeneralArgList] = None,
+ volume_mounts: Optional[Dict[str, str]] = None,
+ envs: Optional[List[str]] = None,
+ privileged: Optional[bool] = None,
+ ):
+ self.image = image
+ self.entrypoint = entrypoint
+ self.entrypoint_args: Optional[ArgumentList] = None
+ if entrypoint_args:
+ self.entrypoint_args = ArgumentSpec.from_general_args(
+ entrypoint_args
+ )
+ self.volume_mounts = volume_mounts
+ self.envs = envs
+ self.privileged = privileged
+ self.validate()
+
+ def validate(self) -> None:
+ if all(getattr(self, key) is None for key in self._fields):
+ raise SpecValidationError(
+ 'At least one parameter must be set (no values were specified)'
+ )
+
+ def to_json(self, flatten_args: bool = False) -> Dict[str, Any]:
+ data: Dict[str, Any] = {}
+ for key in self._basic_fields:
+ value = getattr(self, key, None)
+ if value is not None:
+ data[key] = value
+ if self.entrypoint_args and flatten_args:
+ data['entrypoint_args'] = sum(
+ (ea.to_args() for ea in self.entrypoint_args), []
+ )
+ elif self.entrypoint_args:
+ data['entrypoint_args'] = ArgumentSpec.map_json(
+ self.entrypoint_args
+ )
+ return data
+
+ def __repr__(self) -> str:
+ vals = ((key, getattr(self, key)) for key in self._fields)
+ contents = ", ".join(f'{key}={val!r}' for key, val in vals if val)
+ return f'InitContainerSpec({contents})'
+
+ @classmethod
+ def from_json(cls, data: Dict[str, Any]) -> 'InitContainerSpec':
+ return cls(
+ image=data.get('image'),
+ entrypoint=data.get('entrypoint'),
+ entrypoint_args=data.get('entrypoint_args'),
+ volume_mounts=data.get('volume_mounts'),
+ envs=data.get('envs'),
+ privileged=data.get('privileged'),
+ )
+
+ @classmethod
+ def import_values(
+ cls, values: List[Union['InitContainerSpec', Dict[str, Any]]]
+ ) -> List['InitContainerSpec']:
+ out: List[InitContainerSpec] = []
+ for value in values:
+ if isinstance(value, dict):
+ out.append(cls.from_json(value))
+ elif isinstance(value, cls):
+ out.append(value)
+ elif hasattr(value, 'to_json'):
+ # This is a workaround for silly ceph mgr object/type identity
+ # mismatches due to multiple python interpreters in use.
+ out.append(cls.from_json(value.to_json()))
+ else:
+ raise SpecValidationError(
+ f"Unknown type for InitContainerSpec: {type(value)}"
+ )
+ return out
+
+
class CustomContainerSpec(ServiceSpec):
def __init__(self,
service_type: str = 'container',