def get(self, config_type, kind, flavor): if kind not in self.configs[config_type]: printe('Unknown %s kind: "%s"' % (config_type, kind), terminate=2) if flavor not in self.configs[config_type][kind]: printe('Unknown {type} flavor for {kind}: "{flavor}"'.format( type=config_type, kind=kind, flavor=flavor), terminate=2) return self.configs[config_type][kind][flavor]
def append(self, *args): for arg in args: if isinstance(arg, str): self.command_args += [arg] elif isinstance(arg, list) or isinstance(arg, tuple): for sub_arg in arg: self.append(sub_arg) else: printe('Error appending argument of unknown type: {}'.format( str(type(arg))), terminate=True) return self
def create(self, driver, **config): command = CommandBuilder('docker-machine', 'create') command.append('--driver', driver) if config.get('swarm_token') is not None: command.append('--swarm') command.append('--swarm-discovery', 'token://{token}'.format(config.get('swarm_token'))) if config.get('swarm_master') is not None: command.append('--swarm-master') if config.get('registry_mirror') is not None: ip = DockerMachine(config.get('registry_mirror')).ip() if not ip: printe('IP for the registry machine could not be determined. ' 'Does that machine have an IP?', terminate=True) command.append('--engine-registry-mirror', 'http://%s:5000' % ip) if config.get('experimental') is not None: command.append('--engine-install-url', 'https://experimental.docker.com') if config.get('neighbor_machine') is not None \ and not config.get('multihost_networking') is not None: printe('Neighbor machine was provided but multihost networking ' 'was not enabled explicitly. Multihost networking must be ' 'enabled if neighboring machine is to be used.', terminate=2) if config.get('multihost_networking') is not None: command.append('--engine-opt', 'default-network=overlay:multihost') command.append('--engine-label', 'com.docker.network.driver.overlay.' 'bind_interface=eth0') if config.get('neighbor_machine') is not None: command.append('--engine-label', 'com.docker.network.driver.overlay.' 'neighbor_ip={ip}'.format( DockerMachine( config.get('neighbor_machine')).ip())) if config.get('consul') is not None: if isinstance(config.get('consul'), str): consul_name = config.get('consul') else: consul_name = 'consul' command.append('--engine-opt', 'kv-store=consul:{ip}:8500'.format( DockerMachine(consul_name).ip())) command.append(self.name) return command.run()
def create(self, image, *command_args, **config): command = self.base_command() if config is None: config = dict() if config.get('run') is True: command.append('run') if config.get('detach') is True: command.append('--detach') else: command.append('create') command.append('--name', self.name) if config.get('tty') is not None: command.append('--tty') if config.get('interactive') is not None: command.append('--interactive') if config.get('privileged') is True: command.append('--privileged') if config.get('user') is not None: command.append('--user', config.get('user')) for cap in config.get('capabilities', list()): command.append('--cap-add', cap) if config.get('device') is not None: command.append('--device', config.get('device')) for env_var in config.get('environment', dict()): value = config.get('environment')[env_var] if value is True: value = 'true' elif value is False: value = 'false' elif isinstance(value, dict) or isinstance(value, list): value = json.dumps(value) command.append('--env', '%s=%s' % (env_var, str(value))) for exp_port in config.get('expose', list()): command.append('--expose', exp_port) for link in config.get('links', list()): if not re.match(r'.+:.+', link): printe('Error: In {name}, the link "{link}" does not contain' ' both a container name and an alias. ' 'Example = name:alias'.format( name=self.name, link=link, ), terminate=True) command.append('--link', link) if config.get('net') is not None: command.append('--net', config.get('net')) if config.get('ports') is not None: ip = self.machine.ip() if self.machine is not None else None for port in config.get('ports'): if not re.match(r'.+:.+', port): printe('Error: In {name}, the port "{port}" does not ' 'contain both internal and external port.'.format( self.name, port), terminate=True) if ip and port.startswith(':'): port = ip + port command.append('-p', port) if config.get('restart') is True: command.append('--restart', 'always') for volume in config.get('volumes', list()): command.append('--volume', volume) if config.get('volumes-from') is not None: command.append('--volumes-from', config.get('volumes-from')) command.append(image) pattern = re.compile(r"{{([\w\-_]+)}}") for arg in command_args: for match in pattern.finditer(arg): name = match.group(1) if name == 'machine': if self.machine is not None: ip = self.machine.ip() else: ip = None else: try: printe('Looking for machine with name %s' % name) ip = DockerMachine(name).ip() except: printe('Looking for neighboring container with ' 'name {name}'.format(name)) ip = DockerContainer(name, self.machine.name).ip() if ip is None: ip = '127.0.0.1' arg = arg.replace(match.group(0), ip) command.append(arg) return command.run()
parser.add_argument('kind:flavor', nargs='?', help='Of form "kind:flavor". Kinds available are ' 'determined by the kinds in the config ' 'directory. Use the actions "kinds" to look up ' 'all available options.') args = parser.parse_args() if args.debug is True: os.environ['UTILS_DEBUG'] = 'true' elif args.debug is False: os.environ['UTILS_DEBUG'] = 'false' if args.action == 'create' or args.action == 'run' \ and not vars(args)['kind:flavor']: printe('No kind provided for action "create".') printe(parser.format_usage(), terminate=2) if args.action not in actions_without_name and not args.name: if args.action in ('desc', 'describe'): printe('Container kind:flavor required for action "{action}". Use ' 'action "kinds" to list available options.'.format( args.action), terminate=2) printe('Container name required for action "{action}".'.format( args.action), terminate=2) config_manager = ConfigManager(args.config_directory, filter='container') if args.action in ('run', 'create', 'describe', 'desc'): # if not args.machine and args.host:
def stop(self): if self.local: printe("Machine name not provided: Won't try to stop local.") return CommandBuilder('docker-machine', 'stop', self.name).run()
def ssh(self): if self.local: printe("Machine name not provided: Won't try to ssh to local.") return CommandBuilder('docker-machine', 'ssh', self.name).run(replaceForeground=True)
def remove(self): if self.local: printe("Machine name not provided: Cannot remove a local Docker " "instance.") return CommandBuilder('docker-machine', 'rm', self.name).run()
help='Whether or not this machine will be a swarm ' 'master.') parser.add_argument('action', choices=action_mappings, help='The action to perform: {actions}'.format( ', '.join(action_mappings))) parser.add_argument('name', nargs='?', help='The name of the machine to use.') args = parser.parse_args() if args.debug is True: os.environ['UTILS_DEBUG'] = 'true' elif args.debug is False: os.environ['UTILS_DEBUG'] = 'false' config_manager = ConfigManager(args.config_directory, filter='machine') if args.action not in actions_without_name and not args.name: printe('Action "%s" requires a name.' % args.action) printe(parser.format_usage(), terminate=2) if args.action == 'kinds': printe("Here's a list of available kinds to create machines from:", flush=True) print('\n'.join(config_manager.listMachines()), flush=True) printe('To create one, use the "create" action, supply a name, and ' 'put kind:flavor on the end.') elif args.action in actions_without_name: action_mappings[args.action]() elif args.action == 'create': machine_config = dict(vars(args)) if 'consul_machine' in machine_config: machine_config['consul'] = machine_config['consul_machine'] del machine_config['consul_machine']
def create(self, image, *command_args, **config): command = self.base_command() if config is None: config = dict() if config.get('run') is True: command.append('run') if config.get('detach') is True: command.append('--detach') else: command.append('create') command.append('--name', self.name) if config.get('tty') is not None: command.append('--tty') if config.get('interactive') is not None: command.append('--interactive') if config.get('privileged') is True: command.append('--privileged') if config.get('user') is not None: command.append('--user', config.get('user')) for cap in config.get('capabilities', list()): command.append('--cap-add', cap) if config.get('device') is not None: command.append('--device', config.get('device')) for env_var in config.get('environment', dict()): value = config.get('environment')[env_var] if value is True: value = 'true' elif value is False: value = 'false' elif isinstance(value, dict) or isinstance(value, list): value = json.dumps(value) command.append('--env', '%s=%s' % (env_var, str(value))) for exp_port in config.get('expose', list()): command.append('--expose', exp_port) for link in config.get('links', list()): if not re.match(r'.+:.+', link): printe('Error: In {name}, the link "{link}" does not contain' ' both a container name and an alias. ' 'Example = name:alias'.format( name=self.name, link=link, ), terminate=True) command.append('--link', link) if config.get('net') is not None: command.append('--net', config.get('net')) if config.get('ports') is not None: ip = self.machine.ip() if self.machine is not None else None for port in config.get('ports'): if not re.match(r'.+:.+', port): printe('Error: In {name}, the port "{port}" does not ' 'contain both internal and external port.' .format(self.name, port), terminate=True) if ip and port.startswith(':'): port = ip + port command.append('-p', port) if config.get('restart') is True: command.append('--restart', 'always') for volume in config.get('volumes', list()): command.append('--volume', volume) if config.get('volumes-from') is not None: command.append('--volumes-from', config.get('volumes-from')) command.append(image) pattern = re.compile(r"{{([\w\-_]+)}}") for arg in command_args: for match in pattern.finditer(arg): name = match.group(1) if name == 'machine': if self.machine is not None: ip = self.machine.ip() else: ip = None else: try: printe('Looking for machine with name %s' % name) ip = DockerMachine(name).ip() except: printe('Looking for neighboring container with ' 'name {name}'.format(name)) ip = DockerContainer(name, self.machine.name).ip() if ip is None: ip = '127.0.0.1' arg = arg.replace(match.group(0), ip) command.append(arg) return command.run()
help='The name of the container to be used.') parser.add_argument('kind:flavor', nargs='?', help='Of form "kind:flavor". Kinds available are ' 'determined by the kinds in the config ' 'directory. Use the actions "kinds" to look up ' 'all available options.') args = parser.parse_args() if args.debug is True: os.environ['UTILS_DEBUG'] = 'true' elif args.debug is False: os.environ['UTILS_DEBUG'] = 'false' if args.action == 'create' or args.action == 'run' \ and not vars(args)['kind:flavor']: printe('No kind provided for action "create".') printe(parser.format_usage(), terminate=2) if args.action not in actions_without_name and not args.name: if args.action in ('desc', 'describe'): printe('Container kind:flavor required for action "{action}". Use ' 'action "kinds" to list available options.'.format( args.action), terminate=2) printe('Container name required for action "{action}".'.format( args.action), terminate=2) config_manager = ConfigManager(args.config_directory, filter='container') if args.action in ('run', 'create', 'describe', 'desc'): # if not args.machine and args.host: # args.machine = re.search(r"\w+\://([^:]+)(?:\:[0-9]+)?", # args.host).group(1)
def __init__(self, config_directory, filter=None): if config_directory.startswith('~'): config_directory = os.path.expanduser('~') + config_directory[1:] if not os.path.exists(config_directory): os.makedirs(config_directory) try: configs = os.listdir(config_directory) except: printe('Could not list files in the directory:', config_directory, terminate=True) self.configs = {} for config in configs: if not config.endswith('.json'): continue with open('%s/%s' % (config_directory, config)) as file: configJson = json.load(file) if filter and configJson['type'] != filter: continue for field in required_fields: if field not in configJson: printe('Config %s is missing its %s.' % (config, field), terminate=3) if configJson['type'] == 'container': all_fields = list(required_fields) all_fields += required_container_fields all_fields += optional_container_fields for field in configJson: if field not in all_fields: printe('Container config {config} has unknown field ' '"{field}".'.format(config=config, field=field), terminate=3) for field in required_container_fields: if field not in configJson: printe('Container config {config} is missing its ' 'field.'.format(config=config, field=field), terminate=3) for field in optional_container_fields: if field not in configJson: configJson[field] = optional_container_fields[field] elif configJson['type'] == 'machine': all_fields = list(required_fields) all_fields += required_machine_fields all_fields += optional_machine_fields for field in configJson: if field not in all_fields: printe('Machine config {config} has unknown field ' '"{field}".'.format(config=config, field=field), terminate=3) for field in required_machine_fields: if field not in configJson: printe('Machine config {config} is missing its ' '{field}.'.format(config=config, field=field), terminate=3) for field in optional_machine_fields: if field not in configJson: configJson[field] = optional_machine_fields[field] else: printe('Unknown type "{}". Available types are: container, ' 'machine'.format(configJson['type']), terminate=3) config_type = configJson['type'] kind = configJson['kind'] flavor = configJson['flavor'] if config_type not in self.configs: self.configs[config_type] = {} if kind not in self.configs[config_type]: self.configs[config_type][kind] = {} elif flavor in self.configs[config_type][kind]: printe( "Duplicate kind:flavor configs found: {file} {config}. " "Please change or remove one of these configs to have a " "different kind:flavor combination.".format( file=self.configs[config_type][kind][flavor] .get('file_name'), config=config, ), terminate=True ) del configJson['type'] del configJson['kind'] del configJson['flavor'] configJson['file_name'] = config self.configs[config_type][kind][flavor] = configJson