Пример #1
0
 def _service_restart_policy(self, restart_policy_dict: Dict) -> None:
     """
     Converts the parameters in deploy[restart_policy] into a RestartPolicy
     class as expected by docker-py lib.
     """
     self.restart_policy = RestartPolicy(
         condition=restart_policy_dict.get('condition') or 'none',
         delay=convert_time_to_secs(restart_policy_dict.get('delay')) or 0,
         max_attempts=restart_policy_dict.get('max_attempts') or 0,
         window=convert_time_to_secs(restart_policy_dict.get('window'))
         or 0)
Пример #2
0
    def _send_signal_in_swarm(self):
        current_container_id = get_current_container_id()
        if not current_container_id:
            return

        current_container = self.client.containers.get(current_container_id)
        if not current_container:
            return

        image = current_container.attrs['Config'].get('Image')
        if not image:
            return

        command = [sys.executable, __file__, '--label', self.label_name]

        log_driver = current_container.attrs['HostConfig']['LogConfig']['Type']
        log_config = current_container.attrs['HostConfig']['LogConfig'][
            'Config']

        sender = self.client.services.create(
            image=image,
            command=command,
            name='domain-automation-signal-%d-%d' %
            (int(time.time() * 1000), random.randint(100, 999)),
            env=['PYTHONPATH=%s' % os.environ.get('PYTHONPATH', '.')],
            log_driver=log_driver,
            log_driver_options=log_config,
            mode=ServiceMode('global'),
            restart_policy=RestartPolicy(condition='none', max_attempts=0),
            mounts=['/var/run/docker.sock:/var/run/docker.sock:ro'])

        max_wait = 60
        start_time = time.time()

        while abs(time.time() - start_time) < max_wait:
            if all(task['DesiredState'] == 'shutdown'
                   for task in sender.tasks()):
                break

            time.sleep(1)

        states = list(task['Status']['State'] for task in sender.tasks())
        logs = ''.join(
            item.decode() if hasattr(item, 'decode') else item
            for item in sender.logs(stdout=True, stderr=True)).strip()

        sender.remove()

        logger.info('Signalled containers with label %s - result: %s' %
                    (self.label_name, ', '.join(map(str, states))))

        if logs:
            logger.info('Signal logs: %s' % logs)
    def test_service_restart_policy(self):
        restart_policy = {
            'restart_policy': {
                'condition': 'none',
                'delay': '3s',
                'max_attempts': 5,
                'window': 0
            }
        }
        svc = Service(name=self.svc_name, deploy=restart_policy)
        rest_config = RestartPolicy(condition='none',
                                    delay=3,
                                    max_attempts=5,
                                    window=0)

        self.assertEquals(svc.restart_policy, rest_config)
    def test_service_restart_policy_with_additional_parameters(self):
        restart_policy = {
            'restart_policy': {
                'condition': 'none',
                'delay': '3s',
                'max_attempts': 5,
                'test': 'unused_parameter'
            }
        }
        svc = Service(name=self.svc_name, deploy=restart_policy)
        rest_config = RestartPolicy(condition='none',
                                    delay=3,
                                    max_attempts=5,
                                    window=0)

        self.assertEquals(svc.restart_policy, rest_config)
Пример #5
0
    def configure(cls, image, service, secrets=None, mounts=None, **kwargs):
        self = ServiceKwargs()
        options = service.options
        deploy_opts = options.get("deploy", {})
        prefs = deploy_opts.get("placement", {}).get("preferences", {})

        # Map compose options to service options
        self.image = image
        self.constraints = deploy_opts.get("placement", {}).get("constraints")
        self.preferences = [kv for pref in prefs for kv in pref.items()]
        self.container_labels = options.get("labels")

        self.endpoint_spec = EndpointSpec(
            deploy_opts.get("endpoint_mode"),
            {p.published: p.target
             for p in options.get("ports", [])})

        self.env = options.get("environment", None)
        self.hostname = options.get("hostname")
        self.isolation = options.get("isolation")
        self.labels = {
            k: v
            for k, v in (kv.split('=') for kv in deploy_opts.get("labels", []))
        }
        self.log_driver = options.get("logging", {}).get("driver")
        self.log_driver_options = options.get("logging", {}).get("options")
        self.mode = ServiceMode(deploy_opts.get("mode", "replicated"),
                                deploy_opts.get("replicas", 1))
        self.networks = [
            config.SWARM_NETWORK
        ]  # Similar to mounts. I don't see the use case but see the issues

        resource_opts = deploy_opts.get("resources", {})
        if resource_opts:
            # Unpack any generic_resources defined i.e. gpus and such
            reservation_opts = resource_opts.get("reservations", {})
            generic_resources = {}
            for generic_resource in reservation_opts.get(
                    "generic_resources", {}):
                discrete_resource_spec = generic_resource[
                    "discrete_resource_spec"]
                generic_resources[discrete_resource_spec[
                    "kind"]] = discrete_resource_spec["value"]
            cpu_limit = sfloat(resource_opts.get("limits", {}).get("cpus"), 0)
            cpu_reservation = sfloat(reservation_opts.get("cpus"), 0)
            nano_cpu_limit = sint(cpu_limit *
                                  1e9, 0) if cpu_limit is not None else None
            nano_cpu_reservation = sint(
                cpu_reservation *
                1e9, 0) if cpu_reservation is not None else None
            self.resources = Resources(
                cpu_limit=nano_cpu_limit,
                mem_limit=parse_bytes(
                    resource_opts.get("limits", {}).get("memory", '')),
                cpu_reservation=nano_cpu_reservation,
                mem_reservation=parse_bytes(reservation_opts.get("memory",
                                                                 '')),
                generic_resources=generic_resources)

        restart_opts = deploy_opts.get("restart_policy", {})
        if restart_opts:
            # Parse the restart policy
            delay = timeparse(restart_opts.get("delay", "0s"))
            window = timeparse(restart_opts.get("restart_opts", "0s"))
            self.restart_policy = RestartPolicy(
                condition=restart_opts.get("condition", ),
                delay=delay,
                max_attempts=sint(restart_opts.get("max_attempts", 0), 0),
                window=window)

        self.secrets = secrets
        self.mounts = mounts

        # Grab any key word arguments that may have been given
        [setattr(self, k, v) for k, v in kwargs.items() if hasattr(self, k)]

        service_kwargs = _get_create_service_kwargs('create',
                                                    copy.copy(self.__dict__))

        # This is needed because aiodocker assumes the Env is a dictionary for some reason...
        if self.env is not None:
            service_kwargs["task_template"]["ContainerSpec"]["Env"] = self.env

        return service_kwargs
Пример #6
0
    def configure(self, service, secrets=None):
        """ Parameters:
                image (str) – The image name to use for the containers.
                command (list of str or str) – Command to run.
                args (list of str) – Arguments to the command.
                constraints (list of str) – Placement constraints.
                preferences (list of tuple) – Placement preferences.
                platforms (list of tuple) – A list of platform constraints expressed as (arch, os) tuples.
                container_labels (dict) – Labels to apply to the container.
                endpoint_spec (EndpointSpec) – Properties that can be configured to access and load balance a service. Default: None.
                env (list of str) – Environment variables, in the form KEY=val.
                hostname (string) – Hostname to set on the container.
                isolation (string) – Isolation technology used by the service’s containers. Only used for Windows containers.
                labels (dict) – Labels to apply to the service.
                log_driver (str) – Log driver to use for containers.
                log_driver_options (dict) – Log driver options.
                mode (ServiceMode) – Scheduling mode for the service. Default:None
                mounts (list of str) – Mounts for the containers, in the form source:target:options, where options is either ro or rw.
                name (str) – Name to give to the service.
                networks (list of str) – List of network names or IDs to attach the service to. Default: None.
                resources (Resources) – Resource limits and reservations.
                restart_policy (RestartPolicy) – Restart policy for containers.
                secrets (list of docker.types.SecretReference) – List of secrets accessible to containers for this service.
                stop_grace_period (int) – Amount of time to wait for containers to terminate before forcefully killing them.
                update_config (UpdateConfig) – Specification for the update strategy of the service. Default: None
                rollback_config (RollbackConfig) – Specification for the rollback strategy of the service. Default: None
                user (str) – User to run commands as.
                workdir (str) – Working directory for commands to run.
                tty (boolean) – Whether a pseudo-TTY should be allocated.
                groups (list) – A list of additional groups that the container process will run as.
                open_stdin (boolean) – Open stdin
                read_only (boolean) – Mount the container’s root filesystem as read only.
                stop_signal (string) – Set signal to stop the service’s containers
                healthcheck (Healthcheck) – Healthcheck configuration for this service.
                hosts (dict) – A set of host to IP mappings to add to the container’s hosts file.
                dns_config (DNSConfig) – Specification for DNS related configurations in resolver configuration file.
                configs (list) – List of ConfigReference that will be exposed to the service.
                privileges (Privileges) – Security options for the service’s containers.
        """

        options = service.options
        deploy_opts = options.get("deploy", {})
        prefs = deploy_opts.get("placement", {}).get("preferences", {})

        # Map compose options to service options
        self.constraints = deploy_opts.get("placement", {}).get("constraints")
        self.preferences = [kv for pref in prefs for kv in pref.items()]
        self.container_labels = options.get("labels")

        self.endpoint_spec = EndpointSpec(
            deploy_opts.get("endpoint_mode"),
            {p.published: p.target
             for p in options.get("ports", [])})

        self.env = [f"{k}={v}" for k, v in options.get("environment").items()]
        self.hostname = options.get("hostname")
        self.isolation = options.get("isolation")
        self.labels = {
            k: v
            for k, v in (kv.split('=') for kv in deploy_opts.get("labels", []))
        }
        self.log_driver = options.get("logging", {}).get("driver")
        self.log_driver_options = options.get("logging", {}).get("options")
        self.mode = ServiceMode(deploy_opts.get("mode", "replicated"),
                                deploy_opts.get("replicas", 1))
        self.mounts = None  # I'm not sure we should allow mounting volumes to apps until I see a use case
        self.name = service.name
        self.networks = None  # Similar to mounts. I don't see the use case but see the issues

        resource_opts = deploy_opts.get("resources", {})
        if resource_opts:
            # Unpack any generic_resources defined i.e. gpus and such
            reservation_opts = resource_opts.get("reservations", {})
            generic_resources = {}
            for generic_resource in reservation_opts.get(
                    "generic_resources", {}):
                discrete_resource_spec = generic_resource[
                    "discrete_resource_spec"]
                generic_resources[discrete_resource_spec[
                    "kind"]] = discrete_resource_spec["value"]
            cpu_limit = sfloat(resource_opts.get("limits", {}).get("cpus"))
            cpu_reservation = sfloat(reservation_opts.get("cpus"))
            nano_cpu_limit = sint(cpu_limit *
                                  1e9) if cpu_limit is not None else None
            nano_cpu_reservation = sint(
                cpu_reservation * 1e9) if cpu_reservation is not None else None
            self.resources = Resources(
                cpu_limit=nano_cpu_limit,
                mem_limit=parse_bytes(
                    resource_opts.get("limits", {}).get("memory", '')),
                cpu_reservation=nano_cpu_reservation,
                mem_reservation=parse_bytes(reservation_opts.get("memory",
                                                                 '')),
                generic_resources=generic_resources)

        restart_opts = deploy_opts.get("restart_policy", {})
        if restart_opts:
            # Parse the restart policy
            delay = timeparse.timeparse(restart_opts.get("delay", "0s"))
            window = timeparse.timeparse(restart_opts.get(
                "restart_opts", "0s"))
            self.restart_policy = RestartPolicy(
                condition=restart_opts.get("condition", ),
                delay=delay,
                max_attempts=sint(restart_opts.get("max_attempts", 0)),
                window=window)

        # self.secrets = [SecretReference(secret_id=s["secret"].uid, secret_name=s["secret"].name, filename=s.get("file", s["secret"].name), uid=s["secret"].uid, gid=s["secret"].gid, mode=s["secret"].mode) for s in service.secrets]
        # self.secrets = self.load_secrets(service)

        return {
            key: value
            for key, value in self.as_dict().items() if value is not None
        }