def test_anon_volumes(self):
        """
        Make sure that anonymous volumes are correctly registered

        Currently unimplemented and will fail
        """
        self.image = 'busybox'
        self.conf = {
            "image": self.image,
            "container": {
                "name": self.container_name,
                "hostname": "busybox",
                "volumes": ["/var"]
            }
        }
        serv = create_service(self.conf, './Controlfile')
        container = Container(serv).create(prod=False)
        container.start()
        self.assertEqual(len(container.inspect['Mounts']), 1)
        self.assertEqual(len(container.inspect['Mounts'][0]['Name']), 65)
        self.assertEqual(container.inspect['Mounts'][0]['Destination'], '/var')
        self.assertTrue(container.inspect['Mounts'][0]['Source'].startswith(
            '/var/lib/docker/volumes'),
                        msg="Unexpected mount source: {}".format(
                            container.inspect['Mount'][0]['Source']))
 def test_named_volumes(self):
     """Make sure that named volumes are correctly registered"""
     volume_name = "control_unittest_volume{}".format(
         random.randint(1, 65535))
     self.container_volumes.append(volume_name)
     self.image = 'busybox'
     self.conf = {
         "image": self.image,
         "container": {
             "name": self.container_name,
             "hostname": "busybox",
             "volumes": ["{}:/var".format(volume_name)]
         }
     }
     serv = create_service(self.conf, './Controlfile')
     container = Container(serv).create(prod=False)
     container.start()
     self.assertEqual(len(container.inspect['Mounts']), 1)
     self.assertEqual(len(container.inspect['Mounts'][0]['Name']),
                      len(volume_name))
     self.assertEqual(container.inspect['Mounts'][0]['Destination'], '/var')
     self.assertTrue(container.inspect['Mounts'][0]['Source'].startswith(
         '/var/lib/docker/volumes'),
                     msg="Unexpected mount source: {}".format(
                         container.inspect['Mounts'][0]['Source']))
Ejemplo n.º 3
0
 def test_happy_path(self):
     """Make sure that the defaults still work"""
     self.conf = {
         "image": 'busybox',
         "container": {
             "name": self.container_name,
             "hostname": "happy_path"
         }
     }
     serv = create_service(deepcopy(self.conf), './Controlfile')
     container = Container(serv)
     self.assertEqual(container.service.expected_timeout, 10)
     self.assertEqual(container.service['name'], self.container_name)
     self.assertEqual(container.service['hostname'], self.conf['container']['hostname'])
     self.assertEqual(container.service.image, self.conf['image'])
Ejemplo n.º 4
0
def start(args, ctrl):
    """starting containers"""
    no_err = True
    for service in sorted((ctrl.services[name]
                           for name in args.services
                           if isinstance(ctrl.services[name], Startable))):

        container = Container(service)
        if options.no_volumes:
            container.disable_volumes()

        upstream = Repository.match(service.image)
        if module_logger.isEnabledFor(logging.DEBUG):
            module_logger.debug('pull deciders')
            module_logger.debug('not container.image_exists(): %s', not container.image_exists())
            module_logger.debug('not service.buildable(): %s', not service.buildable())
            module_logger.debug('pulling(upstream): %s', pulling(upstream))
            should_pull = not container.image_exists() and not service.buildable() and pulling(upstream)
        if not options.dump and should_pull:
            pull_image(upstream)
        elif options.dump and should_pull:
            # TODO: print pull command
            pass

        try:
            # TODO: if a container exists but the options don't match, log out that
            # we are starting a container that does not match the merged controlfile
            # and cli options
            container = CreatedContainer(service['name'], service)
        except ContainerDoesNotExist:
            pass  # This will probably be the majority case
        if options.dump:
            print(container.service.dump_run(prod=options.prod))
        else:
            print('Starting {}'.format(service['name']))
            try:
                container = container.create(prod=options.prod)
                container.start()
            except ContainerException as e:
                module_logger.debug('outer start containerexception caught')
                module_logger.critical(e)
                no_err = False
            except ImageNotFound as e:
                module_logger.critical(e)
                no_err = False
    return no_err
Ejemplo n.º 5
0
 def test_expected_timeout(self):
     """Test mirroring unspecified values and overriding default timeout"""
     self.conf = {
         "image": 'busybox',
         "expected_timeout": 3,
         "container": {
             "name": self.container_name
         }
     }
     serv = create_service(deepcopy(self.conf), './Controlfile')
     container = Container(serv)
     self.assertEqual(container.service.expected_timeout, 3)
     self.assertEqual(container.service['name'], self.container_name)
     self.assertEqual(
         container.service['hostname'],
         self.container_name,
         msg='Unspecified hostname not being mirrored from container name')
     self.assertEqual(container.service.image, self.conf['image'])
Ejemplo n.º 6
0
def opencontainer(args, ctrl):
    """handles opening a container for dev work"""
    if len(args.services) > 1:
        print('Cannot open more than 1 service in 1 call')
        return False
    name = args.services[0]
    serv = ctrl.services[name]
    try:
        if isinstance(ctrl.services[name]['open'], list):
            (
                ctrl.services[name]['entrypoint'],
                ctrl.services[name]['command']) = (
                    ctrl.services[name]['open'][0],
                    ctrl.services[name]['open'][1:])
        elif isinstance(ctrl.services[name]['open'], str):
            # split on the first space
            ctrl.services[name]['entrypoint'], \
                ctrl.services[name]['command'] = \
                ctrl.services[name]['open'].partition(' ')[::2]
    except KeyError:
        print("'open' not defined for service. Using /bin/sh as entrypoint")
        ctrl.services[name]['entrypoint'] = '/bin/sh'
        ctrl.services[name]['command'] = ''
    ctrl.services[name]['stdin_open'] = True
    ctrl.services[name]['tty'] = True
    if options.dump:
        print(serv.dump_run())
        return True

    try:
        container = CreatedContainer(ctrl.services[name]['name'], ctrl.services[name])
    except ContainerDoesNotExist:
        pass  # We need the container to not exist
    else:
        if not (container.stop() and container.remove()):
            print('could not stop {}'.format(ctrl.services[name]['name']))
            return False
    container = Container(ctrl.services[name]).create(prod=options.prod)
    os.execlp('docker', 'docker', 'start', '-a', '-i', ctrl.services[name]['name'])
    def test_mounted_volumes(self):
        """Make sure that mounted volumes are correctly registered"""
        import tempfile

        temp_dir = tempfile.TemporaryDirectory()
        self.image = 'busybox'
        self.conf = {
            "image": self.image,
            "container": {
                "name": self.container_name,
                "hostname": "busybox",
                "volumes": ["{}:/var".format(temp_dir.name)]
            }
        }
        serv = create_service(self.conf, './Controlfile')
        container = Container(serv).create(prod=False)
        container.start()
        self.assertEqual(len(container.inspect['Mounts']), 1)
        self.assertEqual(container.inspect['Mounts'][0]['Destination'], '/var')
        self.assertTrue(
            container.inspect['Mounts'][0]['Source'] == temp_dir.name,
            msg="Unexpected mount source: {}".format(
                container.inspect['Mounts'][0]['Source']))
        temp_dir.cleanup()
Ejemplo n.º 8
0
def command(args, ctrl):
    """
    Call a custom command on a container. If the container wasn't running
    before the command was run, then the container is left in  the same state.
    """
    module_logger.debug(", ".join(sorted(args.services)))
    no_err = True
    services = sorted(
        ctrl.services[name]
        for name in args.services
        if (options.command in ctrl.services[name].commands.keys() or
            '*' in ctrl.services[name].commands.keys()))
    for service in services:
        if len(services) > 1:
            module_logger.info('running command in %s', service['name'])
        cmd = service.commands[options.command
                               if options.command in service.commands.keys()
                               else '*'
                              ].format(COMMAND=options.command)

        # Check if the container is running. If we need to run the command
        # exclusively, take down the container.
        # Once that decision is made, we need the container running. Exec'ing
        # a command into a running container produces better output than
        # running the container with the command, so we run the container
        # with a command that simply holds the container open so we can exec
        # the command we want into the container.
        put_it_back = False
        try:
            container = CreatedContainer(service['name'], service)
            if options.replace:
                if options.dump:
                    print(
                        builder('stop').container(service['name']).time(service.expected_timeout)
                    )
                    print(
                        builder('rm').container(service['name']).time(service.expected_timeout)
                    )
                else:
                    container.stop()
                    container.remove()
                put_it_back = True
                raise ContainerDoesNotExist(service['name'])
            if not container.inspect['State']['Running']:
                container.remove()
                raise ContainerDoesNotExist(service['name'])
            else:
                kill_it = False
        except ContainerDoesNotExist:
            module_logger.debug("saving service: ('%s', '%s')",
                                service['entrypoint'],
                                service['command'])
            saved_entcmd = (service['entrypoint'], service['command'], service['stdin_open'])
            service['entrypoint'] = '/bin/cat'
            service['command'] = ''
            service['stdin_open'] = True
            service['tty'] = True
            container = Container(service)
            kill_it = True
            # TODO: when does this get printed?
            # if not options.dump:
            #     print(service.dump_run())
            # else:
            if not options.dump:
                try:
                    container = container.create(prod=options.prod)
                    container.start()
                except ImageNotFound as e:
                    module_logger.critical(e)
                    continue
                except ContainerException as e:
                    module_logger.debug('outer start containerexception caught')
                    module_logger.critical(e)
                    no_err = False
        # module_logger.debug('Container running: %s', container.inspect['State']['Running'])
        # time.sleep(1)
        # container.check()
        # module_logger.debug('Container running: %s', container.inspect['State']['Running'])

        # We take the generator that docker gives us for the exec output and
        # print it to the console. The Exec spawned a TTY so programs that care
        # will output color.
        if options.dump and not kill_it:
            print(builder('exec', pretty=False).container(service['name']).command(cmd).tty())
        elif options.dump:
            ent_, _, cmd_ = cmd.partition(' ')
            run = service.dump_run() \
                .entrypoint(ent_) \
                .command(cmd_) \
                .rm() \
                .tty() \
                .interactive(saved_entcmd[2])
            print(run)
        else:
            gen = (l.decode('utf-8') for l in container.exec(cmd))
            for line in gen:
                print(line, end='')
            if container.inspect_exec()['ExitCode'] != 0:
                no_err = False

        # After the command we make sure to clean up the container. Since we
        # spawned the container running a command that just holds the container
        # open, if we replaced a running container we need to take down this
        # dummy container and start it with its normal entrypoint
        if (put_it_back or kill_it) and not options.dump:
            if options.force:
                module_logger.debug('Killing %s', service['name'])
                container.kill()
            else:
                module_logger.debug('Stopping %s', service['name'])
                container.stop()
            module_logger.debug('Removing %s', service['name'])
            container.remove()
            if options.wipe:
                container.remove_volumes()
        if put_it_back:
            if saved_entcmd[0]:
                service['entrypoint'] = saved_entcmd[0]
            else:
                del service['entrypoint']
            if saved_entcmd[1]:
                service['command'] = saved_entcmd[1]
            else:
                del service['command']
            if isinstance(saved_entcmd[2], bool):
                service['stdin_open'] = saved_entcmd[2]
            else:
                del service['stdin_open']
            module_logger.debug("retrieved service: ('%s', '%s')",
                                service['entrypoint'],
                                service['command'])
            container = Container(service)
            if options.dump:
                print(service.dump_run())
            else:
                try:
                    container = container.create(prod=options.prod)
                    container.start()
                except ContainerException as e:
                    module_logger.debug('outer start containerexception caught')
                    module_logger.critical(e)
                    no_err = False
    return no_err