Esempio n. 1
0
 def test_no_options(self):
     """
     Make sure that with no extra options a valid docker build command is
     created
     """
     result = builder('build')
     self.assertEqual(str(result), "docker build .")
     result = builder('build', pretty=False)
     self.assertEqual(str(result), "docker build .")
Esempio n. 2
0
 def test_list_arg_invalid_type_raises(self):
     """
     Make sure that if something that doesn't boil down to a string
     raises an exception
     """
     result = builder('run', pretty=False).image('busybox').attach(0)
     self.assertEqual(str(result), "docker run --attach 0 busybox")
     result = builder('run', pretty=False).image('busybox').attach([0])
     self.assertEqual(str(result), "docker run --attach 0 busybox")
     result = builder('run', pretty=False).image('busybox').attach({0})
     self.assertEqual(str(result), "docker run --attach 0 busybox")
     result = builder('run', pretty=False).image('busybox').attach((0))
     self.assertEqual(str(result), "docker run --attach 0 busybox")
Esempio n. 3
0
 def test_raises_missing_positional(self):
     """
     docker run needs an image to start a container from, and there's no
     good way to assume a default, so we just force the user to specify an
     image before they try to get the cli command
     """
     result = builder('exec')
     with self.assertRaises(ControlException):
         str(result)
     result = result.container('foo')
     with self.assertRaises(ControlException):
         str(result)
     result = builder('exec').command('ps aux')
     with self.assertRaises(ControlException):
         str(result)
Esempio n. 4
0
 def test_raises_missing_positional(self):
     """
     docker rm should raise an error when there were no containers specified
     """
     result = builder('rm')
     with self.assertRaises(ControlException):
         str(result)
Esempio n. 5
0
 def test_sorting(self):
     """
     Make sure that flags are spit out in alphabetized order so they
     easier to visually inspect. But make sure that multiple arguments to
     flags are kept in the order they were specified, this way we don't
     break intentional overrides
     """
     result = builder('run', pretty=False) \
         .image('ubuntu') \
         .tty() \
         .interactive() \
         .volume('/mnt:/mnt') \
         .volume('/home:/home') \
         .volume('/var/foo:/var/foo') \
         .user('1000') \
         .volume('/var/foo:/usr/share/lib/foo') \
         .volume([
             '/var/lib/bucket:/var/lib/bucket',
             '/home:/home',
         ]) \
         .volume({'/var/log/foo:/foo/log'}) \
         .entrypoint('/bin/bash')
     self.assertEqual(
         str(result),
         "docker run --entrypoint /bin/bash --interactive --tty "
         "--user 1000 "
         "--volume /mnt:/mnt "
         "--volume /home:/home "
         "--volume /var/foo:/var/foo "
         "--volume /var/foo:/usr/share/lib/foo "
         "--volume /var/lib/bucket:/var/lib/bucket "
         "--volume /home:/home "
         "--volume /var/log/foo:/foo/log "
         "ubuntu")
Esempio n. 6
0
 def test_nondefault_path(self):
     """
     Make sure that changing the path from the default results in modified
     output
     """
     result = builder('build', pretty=False).tag('foobar').path('build')
     self.assertEqual(str(result), "docker build --tag foobar build")
Esempio n. 7
0
 def dump_run(self, prod=False, pretty=True):
     """dump out a CLI version of how this container would be started"""
     rep = builder('run', pretty=pretty).image(self.image) \
             .volume(sorted(self.volumes_for(prod)))
     if self.env_file:
         rep = rep.env_file(self.env_file)
     for k, v in self.container.items():
         rep = {
             'command': rep.command,
             'cpu_shares': rep.cpu_shares,
             'detach': rep.detach,
             'entrypoint': rep.entrypoint,
             'environment': rep.env,
             'hostname': rep.hostname,
             'name': rep.name,
             'ports': rep.publish,
             'stdin_open': rep.interactive,
             'tty': rep.tty,
             'user': rep.user,
             'working_dir': rep.workdir,
         }[k](v)
     for k, v in self.host_config.items():
         rep = {
             'devices': rep.device,
             'dns': rep.dns,
             'dns_search': rep.dns_search,
             'extra_hosts': rep.add_host,
             'ipc_mode': rep.ipc,
             'links': rep.link,
             'volumes_from': rep.volumes_from,
         }[k](v)
     return rep.detach()
Esempio n. 8
0
 def test_pass_command_list(self):
     """
     docker-py accepts command as a list. I want to be able to pass that
     straight into this library and have it work correctly
     """
     result = builder('exec',
                      pretty=False).container('foo').command(['ps', 'aux'])
     self.assertEqual(str(result), "docker exec foo ps aux")
Esempio n. 9
0
 def test_pass_command_list(self):
     """
     docker-py accepts command as a list. I want to be able to pass that
     straight into this library and have it work correctly
     """
     result = builder('run',
                      pretty=False).image('busybox').command(['ps', 'aux'])
     self.assertEqual(str(result), "docker run busybox ps aux")
Esempio n. 10
0
 def test_single_values_overwrite(self):
     """
     When you set a single value, and then set it again. The later value
     should have precedence
     """
     result = builder('build',
                      pretty=False).tag('foobar').tag('alpine:test')
     self.assertEqual(str(result), "docker build --tag alpine:test .")
Esempio n. 11
0
 def test_adding_containers(self):
     """make sure that containers are kept in order, and don't error"""
     result = builder('rm').container('abernathy')
     self.assertEqual(str(result), "docker rm abernathy")
     result = result.container(['foo', 'bar']).container({'foobar'})
     result = result.container(('hawking')).container(0)
     self.assertEqual(str(result),
                      "docker rm abernathy foo bar foobar hawking 0")
Esempio n. 12
0
 def test_raises_if_no_image(self):
     """
     docker run needs an image to start a container from, and there's no
     good way to assume a default, so we just force the user to specify an
     image before they try to get the cli command
     """
     result = builder('run').env('FOO=bar').user('1000').detach()
     with self.assertRaises(ControlException):
         str(result)
Esempio n. 13
0
 def test_no_pretty(self):
     """Everything should show up on one line"""
     result = builder('build', pretty=False).tag('busybox').pull().rm()
     self.assertEqual(str(result),
                      "docker build --pull --rm --tag busybox .")
     result = builder('run', pretty=False).image('busybox')
     self.assertEqual(str(result), "docker run busybox")
     result = builder('run', pretty=False) \
         .detach() \
         .tty() \
         .user('foobar') \
         .hostname('foo') \
         .volume('/mnt:/mnt') \
         .image('busybox') \
         .command('cat')
     self.assertEqual(
         str(result), "docker run --detach --hostname foo --tty "
         "--user foobar --volume /mnt:/mnt busybox cat")
Esempio n. 14
0
 def test_bool_arg_removal(self):
     """
     Test that passing a False to a boolean setter removes the option
     from output
     """
     result = builder('build', pretty=False).tty(False)
     self.assertEqual(str(result), "docker build .")
     result = result.tty()
     self.assertEqual(str(result), "docker build --tty .")
     result = result.tty(False)
     self.assertEqual(str(result), "docker build .")
Esempio n. 15
0
 def dump_build(self, prod=False, pretty=True):
     """dump out a CLI version of how this image would be built"""
     rep = builder('build', pretty=pretty) \
         .tag(self.image) \
         .path(dirname(self.controlfile)) \
         .file(self.dockerfile['prod'] if prod else self.dockerfile['dev']) \
         .pull(options.pull) \
         .rm(options.no_rm) \
         .force_rm(options.force) \
         .no_cache(not options.cache)
     return rep
Esempio n. 16
0
 def test_pretty(self):
     """
     Flags should show up one per line. Positional arguments should all be
     on one line.
     """
     result = builder('build').tag('busybox').pull().rm()
     self.assertEqual(
         str(result), "docker build \\\n\t--pull \\\n\t--rm \\\n\t"
         "--tag busybox \\\n\t.")
     result = builder('run').image('busybox')
     self.assertEqual(str(result), "docker run busybox")
     result = builder('run') \
         .detach() \
         .tty() \
         .user('foobar') \
         .hostname('foo') \
         .volume('/mnt:/mnt') \
         .image('busybox') \
         .command('cat')
     self.assertEqual(
         str(result),
         "docker run \\\n\t--detach \\\n\t--hostname foo \\\n\t"
         "--tty \\\n\t--user foobar \\\n\t"
         "--volume /mnt:/mnt \\\n\tbusybox \\\n\tcat")
Esempio n. 17
0
 def test_incompatible_command_raises(self):
     """make sure a command that isn't a list or a string are unhappy"""
     with self.assertRaises(TypeError):
         builder('exec').command((0, 1))
Esempio n. 18
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
Esempio n. 19
0
 def test_tagged(self):
     """Make sure that a tag is stuck on correctly"""
     result = builder('build', pretty=False).tag('foobar')
     self.assertEqual(str(result), "docker build --tag foobar .")
Esempio n. 20
0
 def test_broken_path(self):
     """In case you do weird stuff and null out the default path"""
     result = builder('build').path('')
     with self.assertRaises(ControlException):
         str(result)