def prepare(self, tag=None, **kwargs): """ build Docker image (see 'docker build --help' for available options) """ # default options kwargs.setdefault('pull', True) kwargs.setdefault('force-rm', True) for key, value in kwargs.items(): try: kwargs[key] = utils.strtobool(value) except ValueError: pass options = utils.Options(tag=self.image[self.registry:tag:self.account], **kwargs) fabricio.local( 'docker build {options} {build_path}'.format( build_path=self.build_path, options=options, ), quiet=False, use_cache=True, ) self.delete_dangling_images()
def __get_images_spec(self): template = ( # noqa '{{define "images"}}' '{{$kind := .kind}}' '{{$name := .metadata.name}}' '{{with .spec.template.spec.containers}}' '{{range .}}' r'{{$kind}}/{{$name}} {{.name}} {{.image}}{{"\n"}}' '{{end}}' '{{end}}' '{{end}}' '{{if eq .kind "List"}}' '{{range .items}}{{template "images" .}}{{end}}' '{{else}}' '{{template "images" .}}' '{{end}}') command = ('kubectl get {options}'.format(options=utils.Options([ ('output', 'go-template'), ('filename', os.path.basename(self.config)), ('template', template), ]))) result = dict() for line in filter(None, fabricio.run(command).splitlines()): kind, image_spec = line.split(None, 1) name, image = image_spec.rsplit(None, 1) result.setdefault(kind, dict())[name] = image return result
def _update(self, image, force=False): image = image.digest try: service_info = self.info except ServiceNotFoundError: service_info = {} with utils.patch(self, 'info', service_info, force_delete=True): labels = service_info.get('Spec', {}).get('Labels', {}) current_options = labels.pop(self.options_label_name, None) new_options = self._encode_options( dict( self.options, image=image, args=self.cmd, )) if force or current_options != new_options: label_with_new_options = { self.options_label_name: new_options, } self._update_labels(label_with_new_options) if service_info: options = utils.Options(self.update_options, image=image) self._update_service(options) else: self._create_service(image) return True return False
def delete( self, delete_image=False, delete_dangling_volumes=None, # deprecated **options): options = utils.Options(options) if delete_dangling_volumes is not None: # pragma: no cover warnings.warn( '`delete_dangling_volumes` parameter is deprecated ' 'and will be removed in v0.6, use `volumes` instead', RuntimeWarning, stacklevel=2, ) options.setdefault('volumes', delete_dangling_volumes) delete_image_callback = delete_image and self.image.get_delete_callback( ) options.setdefault('volumes', True) # default option fabricio.run('docker rm {options} {container}'.format( container=self, options=options, )) if delete_image_callback: delete_image_callback()
def _create_service(self, image): command = 'docker service create {options} {image} {cmd}' fabricio.run(command.format( options=utils.Options(self.options, name=self, mode=self.mode), image=image, cmd=self.cmd, ))
def _destroy(self, **options): configuration, _ = self.current_settings if not configuration: raise docker.ServiceError('current configuration not found') with fab.cd(self.temp_dir): self.upload_configuration(configuration) options = utils.Options(options) options.setdefault('filename', self.config) fabricio.run('kubectl delete {options}'.format(options=options))
def _update(self, new_configuration, force=False): if not force: configuration, digests = self.current_settings if configuration == new_configuration and digests is not None: new_digests = self._get_digests(digests) if digests == new_digests: return False options = utils.Options(self.options) command = self.get_update_command(options=options, name=self.name) fabricio.run(command) return True
def _update(self, compose_file, new_settings, force=False): if not force: settings, digests = self.current_settings digests = digests and json.loads(b64decode(digests).decode()) if settings == new_settings and digests is not None: new_digests = self._get_digests(digests, pull=True) if digests == new_digests: return False with fab.cd(self.temp_dir): fab.put(six.BytesIO(compose_file), self.actual_compose_file) fabricio.run('docker stack deploy {options} {name}'.format( options=utils.Options(self.options), name=self.name, )) self.stack_updated.set() return True
def prepare(self, tag=None, **kwargs): """ build Docker image (see 'docker build --help' for available options) """ for key, value in kwargs.items(): with contextlib.suppress(ValueError): kwargs[key] = utils.strtobool(value) options = utils.Options(kwargs) image = self.image[self.registry:tag: self.account] # type: docker.Image image.build( local=True, build_path=self.build_path, options=options, use_cache=True, )
def prepare(self, tag=None, no_cache=False): """ build Docker image """ options = utils.Options([ ('tag', self.image[self.registry:tag:self.account]), ('no-cache', utils.strtobool(no_cache)), ('pull', True), ]) fabricio.local( 'docker build {options} {build_path}'.format( build_path=self.build_path, options=options, ), quiet=False, use_cache=True, ) self.delete_dangling_images()
def destroy(self, **options): """ any passed argument will be forwarded to 'docker stack rm' as option Note: make sure "managers" are listed before "workers" in your Fabricio configuration before calling this method in serial mode """ self._destroy.reset(block=True) try: if self.is_manager(): self._destroy(utils.Options(options)) except ManagerNotFoundError: self._destroy.set() raise timeout = None if fab.env.parallel else 0 self._destroy.wait(timeout) if self._destroy.has_result(): self._remove_images()
def execute( self, command=None, quiet=True, use_cache=False, options=(), ): if not command: raise ValueError('Must provide command to execute') options = utils.Options(options) options.setdefault('tty', True) options.setdefault('interactive', True) exec_command = 'docker exec {options} {container} {command}' return fabricio.run( exec_command.format( container=self, command=command, options=options, ), quiet=quiet, use_cache=use_cache, )
def test_str_version(self): cases = dict( empty_options_list=dict( options=utils.OrderedDict(), expected_str_version='', ), with_underscore=dict( options=utils.OrderedDict(foo_baz='bar'), expected_str_version='--foo_baz=bar', ), multiword=dict( options=utils.OrderedDict(foo='bar baz'), expected_str_version="--foo='bar baz'", ), empty=dict( options=utils.OrderedDict(foo=''), expected_str_version="--foo=''", ), str=dict( options=utils.OrderedDict(foo='bar'), expected_str_version='--foo=bar', ), unicode=dict( options=utils.OrderedDict(foo=u'привет'), expected_str_version=u"--foo='привет'", ), integer=dict( options=utils.OrderedDict(foo=42), expected_str_version='--foo=42', ), integer_zero=dict( options=utils.OrderedDict(foo=0), expected_str_version='--foo=0', ), integer_one=dict( options=utils.OrderedDict(foo=1), expected_str_version='--foo=1', ), integer_minus_one=dict( options=utils.OrderedDict(foo=-1), expected_str_version='--foo=-1', ), image=dict( options=utils.OrderedDict(image=docker.Image('image:tag')), expected_str_version='--image=image:tag', ), triple_length=dict( options=utils.OrderedDict([ ('foo', 'foo'), ('bar', 'bar'), ('baz', 'baz'), ]), expected_str_version='--foo=foo --bar=bar --baz=baz', ), multi_value_empty=dict( options=utils.OrderedDict(foo=[]), expected_str_version='', ), multi_value=dict( options=utils.OrderedDict(foo=['bar', 'baz']), expected_str_version='--foo=bar --foo=baz', ), multi_value_integer=dict( options=utils.OrderedDict(foo=[42, 43]), expected_str_version='--foo=42 --foo=43', ), boolean_values=dict( options=utils.OrderedDict(foo=True, bar=False), expected_str_version='--foo', ), mix=dict( options=utils.OrderedDict([ ('foo', 'foo'), ('bar', True), ('baz', ['1', 'a']), ]), expected_str_version='--foo=foo --bar --baz=1 --baz=a', ), ) for case, params in cases.items(): with self.subTest(case=case): options = utils.Options(params['options']) expected_str_version = params['expected_str_version'] self.assertEqual(expected_str_version, six.text_type(options))
def _destroy(self, **options): fabricio.run('docker stack rm {options} {name}'.format( options=utils.Options(options), name=self.name, ))
def test_str_version(self): cases = dict( empty_options_list=dict( options=utils.OrderedDict(), expected_str_version='', ), with_underscore=dict( options=utils.OrderedDict(foo_baz='bar'), expected_str_version='--foo_baz bar', ), multiword=dict( options=utils.OrderedDict(foo='bar baz'), expected_str_version='--foo "bar baz"', ), empty=dict( options=utils.OrderedDict(foo=''), expected_str_version='--foo ""', ), with_single_quotes=dict( options=utils.OrderedDict(foo="'bar'"), expected_str_version='--foo "\'bar\'"', ), with_double_quotes=dict( options=utils.OrderedDict(foo='"bar"'), expected_str_version='--foo "\\"bar\\""', ), with_quotes_and_spaces=dict( options=utils.OrderedDict(foo='"bar" \'baz\''), expected_str_version='--foo "\\"bar\\" \'baz\'"', ), str=dict( options=utils.OrderedDict(foo='bar'), expected_str_version='--foo bar', ), unicode=dict( options=utils.OrderedDict(foo=u'привет'), expected_str_version=u'--foo привет', ), integer=dict( options=utils.OrderedDict(foo=42), expected_str_version='--foo 42', ), image=dict( options=utils.OrderedDict(image=docker.Image('image:tag')), expected_str_version='--image image:tag', ), triple_length=dict( options=utils.OrderedDict([ ('foo', 'foo'), ('bar', 'bar'), ('baz', 'baz'), ]), expected_str_version='--foo foo --bar bar --baz baz', ), multi_value=dict( options=utils.OrderedDict(foo=['bar', 'baz']), expected_str_version='--foo bar --foo baz', ), multi_value_integer=dict( options=utils.OrderedDict(foo=[42, 43]), expected_str_version='--foo 42 --foo 43', ), boolean_values=dict( options=utils.OrderedDict(foo=True, bar=False), expected_str_version='--foo', ), mix=dict( options=utils.OrderedDict([ ('foo', 'foo'), ('bar', True), ('baz', ['1', 'a']), ]), expected_str_version='--foo foo --bar --baz 1 --baz a', ), ) for case, params in cases.items(): with self.subTest(case=case): options = utils.Options(params['options']) expected_str_version = params['expected_str_version'] self.assertEqual(expected_str_version, six.text_type(options))