コード例 #1
0
def importHost(host):
    sshConfigPath = str(Path.home()) + "/.ssh/config"
    config = ConfigParser(sshConfigPath)
    config.load()
    hostConfig = config.search_host(host)
    if (hostConfig == []):
        raise Exception("Host does not exists in %s" % sshConfigPath)
    return hostConfig
コード例 #2
0
def parse_ssh_config(filename=TMP_SSH_CONF_FILE_NAME, verbose=False):
    """
    Parse the ssh config and return it as list of hosts (dict)
    :param verbose:
    :param filename:
    :return: the ssh conf parsed

    """
    parser = ConfigParser(ssh_config_file=filename)
    parser.load()
    return parser.config_data
コード例 #3
0
 def __init__(self, module):
     self.module = module
     self.params = module.params
     self.user = self.params.get('user')
     self.group = self.params.get('group') or self.user
     self.host = self.params.get('host')
     self.config_file = self.params.get('ssh_config_file')
     self.identity_file = self.params['identity_file']
     self.check_ssh_config_path()
     try:
         self.config = ConfigParser(self.config_file)
     except FileNotFoundError:
         self.module.fail_json(msg="Failed to find %s" % self.config_file)
     self.config.load()
コード例 #4
0
 def __init__(self, api_token):
     self.api_token = api_token
     self.ssh_id = self.get_ssh_keys()
     self.ssh_config = StormParser(expanduser('~/.ssh/config'))
     self.droplet = {}
     self.droplet_attrs = [
         'name', 'disk', 'image', 'size_slug', 'ip_address'
     ]
コード例 #5
0
    def add_host(self, name, user, hostname, key_file):
        sconfig = StormParser(expanduser("~/.ssh/config"))
        sconfig.load()

        # Remove existig hosts with that name to avoid dupes
        try:
            sconfig.delete_host(name)
        except ValueError:
            # Host not found
            pass    
        sconfig.add_host(name, {
            'user': user,
            'hostname': hostname,
            'IdentityFile': key_file,
            "StrictHostKeyChecking": "no"
        })
        sconfig.write_to_ssh_config()
コード例 #6
0
def main():
    args = get_cli_args()

    ssh_config = StormParser()
    ssh_config.load()

    droplets = get_droplets()
    ssh_config_changed = False

    for droplet in droplets:
        ip = droplet.networks["v4"][0]["ip_address"]

        if host_exists(droplet.name, ssh_config):
            if args.force_update:
                ssh_config.update_host(droplet.name, {
                    "hostname": ip,
                    "user": args.user
                })

                with indent(2):
                    puts(get_info(droplet, ip, args))

                ssh_config_changed = True

        else:
            ssh_config.add_host(droplet.name, {
                "hostname": ip,
                "user": args.user
            })
            ssh_config_changed = True

            with indent(2):
                puts(get_info(droplet, ip, args))

    if ssh_config_changed:
        ssh_config.write_to_ssh_config()
    else:
        with indent(2):
            puts(
                colored.red(
                    "all droplets already exists in your ssh config. use --force-update=1 to update."
                ))
コード例 #7
0
def main():
    args = get_cli_args()

    ssh_config = StormParser()
    ssh_config.load()

    droplets = get_droplets()
    ssh_config_changed = False

    for droplet in droplets:
        ip = droplet.networks["v4"][0]["ip_address"]

        if host_exists(droplet.name, ssh_config):
            if args.force_update:
                ssh_config.update_host(
                    droplet.name,
                    {"hostname": ip, "user": args.user}
                )

                with indent(2):
                    puts(get_info(droplet, ip, args))

                ssh_config_changed = True

        else:
            ssh_config.add_host(droplet.name, {"hostname": ip, "user": args.user})
            ssh_config_changed = True

            with indent(2):
                puts(get_info(droplet, ip, args))

    if ssh_config_changed:
        ssh_config.write_to_ssh_config()
    else:
        with indent(2):
            puts(colored.red("all droplets already exists in your ssh config. use --force-update=1 to update."))
コード例 #8
0
 def remove_host(self, name):
     sconfig = StormParser(expanduser("~/.ssh/config"))
     sconfig.load()
     sconfig.delete_host(name)
     sconfig.write_to_ssh_config()
 def __init__(self, api_token):
     self.api_token = api_token
     self.ssh_id = self.get_ssh_keys()
     self.ssh_config = StormParser(expanduser('~/.ssh/config'))
     self.droplet = {}
     self.droplet_attrs = ['name', 'disk', 'image', 'size_slug', 'ip_address']
class DigitalOcean:
    """Automate Digital Ocean droplet deployment & management"""

    def __init__(self, api_token):
        self.api_token = api_token
        self.ssh_id = self.get_ssh_keys()
        self.ssh_config = StormParser(expanduser('~/.ssh/config'))
        self.droplet = {}
        self.droplet_attrs = ['name', 'disk', 'image', 'size_slug', 'ip_address']

    def update_ssh(self):
        """Update ssh config with new ip address and add missing users"""

        self.ssh_config.load()
        users = {'do': 'root', 'do2': 'kaggle'}
        for host in users.keys():
            if self.ssh_config.search_host(host):
                self.ssh_config.update_host(host, {'user': users[host], 'hostname': self.droplet['ip_address']})
            else:
                self.ssh_config.add_host(host, {'user': users[host], 'hostname': self.droplet['ip_address']})
        self.ssh_config.write_to_ssh_config()

    def update_config_script(self, user=None, password=None, authorized_key='id_rsa', hdf=False):
        """Make requisite substitutions in base cloud-config file"""

        with open('cloud-config.txt') as txt:
            user_data = txt.read()

        if user and password:
            user_data = user_data.replace('KAGGLE_CREDENTIALS',
                                          '  - export KAGGLE_USER={0}\n  - export KAGGLE_PASSWD={1}'.format(user,
                                                                                                            password))
            download_instructions = open('download_instructions.txt').read()
            if hdf:
                download_instructions += "\n  - python3 -c 'from kaggle_data import data_to_hdf; data_to_hdf()'"
            user_data = user_data.replace('DATA_DOWNLOAD', download_instructions)

        else:
            user_data = user_data.replace('KAGGLE_CREDENTIALS', '')
            user_data = user_data.replace('DATA_DOWNLOAD', '')

        if authorized_key:
            user_data = user_data.replace('SSH_AUTHORIZED_KEYS', 'ssh-authorized-keys:\n    - {}'.format(
                open(expanduser('~/.ssh/{}.pub'.format(authorized_key))).read()))
        else:
            user_data.replace('SSH_AUTHORIZED_KEYS', '')
        return user_data

    def launch(self, name='kaggle-droplet', region='nyc2', image='ubuntu-16-04-x64', size='512mb', user=None,
               password=None, authorized_key='id_rsa', hdf=False):
        """Launch DigitalOcean droplet instance"""

        user_data = self.update_config_script(user=user, password=password, authorized_key=authorized_key, hdf=hdf)

        droplet = Droplet(token=self.api_token, name=name, region=region, image=image, size_slug=size, backups=False,
                          ssh_keys=self.ssh_id, user_data=user_data)
        droplet.create()

        self.droplet['id'] = droplet.id
        while not self.droplet.get('ip_address', None):
            self.droplet['ip_address'] = droplet.load().ip_address
        self.update_ssh()
        pprint.pprint(('Name: {}'.format(droplet.name), 'Image: {}'.format(droplet.image.get('slug')),
                       'Memory: {}'.format(droplet.size_slug), 'Disk Size: {}'.format(droplet.disk),
                       'IP Address: {}'.format(droplet.ip_address)))

    def get_droplets(self):
        """Get active droplets"""
        manager = Manager(token=self.api_token)
        my_droplets = manager.get_all_droplets()
        return my_droplets

    def destroy(self):
        """Destroy all active droplets"""
        my_droplets = self.get_droplets()
        for droplet in my_droplets:
            droplet.destroy()

    def get_ssh_keys(self):
        """Get ssh keys stored with DigitalOcean"""

        do_ssh_url = 'https://api.digitalocean.com/v2/account/keys'
        headers = dict(Authorization='Bearer {}'.format(self.api_token))
        response = requests.get(url=do_ssh_url, headers=headers)
        ssh_keys = []
        for ssh_key in response.json().get('ssh_keys'):
            ssh_keys.append(ssh_key.get('id'))
        return ssh_keys
コード例 #11
0
class SSHConfig():
    def __init__(self, module):
        self.module = module
        self.params = module.params
        self.user = self.params.get('user')
        self.group = self.params.get('group') or self.user
        self.host = self.params.get('host')
        self.config_file = self.params.get('ssh_config_file')
        self.identity_file = self.params['identity_file']
        self.check_ssh_config_path()
        try:
            self.config = ConfigParser(self.config_file)
        except FileNotFoundError:
            self.module.fail_json(msg="Failed to find %s" % self.config_file)
        self.config.load()

    def check_ssh_config_path(self):
        if self.user:
            self.config_file = os.path.join(
                os.path.expanduser('~%s' % self.user), '.ssh', 'config')
        elif self.config_file is None:
            self.config_file = '/etc/ssh/ssh_config'

        # See if the identity file exists or not, relative to the config file
        if os.path.exists(self.config_file) and self.identity_file is not None:
            dirname = os.path.dirname(self.config_file)
            self.identity_file = os.path.join(dirname, self.identity_file)

            if not os.path.exists(self.identity_file):
                self.module.fail_json(msg='IdentityFile %s does not exist' %
                                      self.params['identity_file'])

    def ensure_state(self):
        hosts_result = self.config.search_host(self.host)
        state = self.params['state']
        args = dict(
            hostname=self.params.get('hostname'),
            port=self.params.get('port'),
            identity_file=self.params.get('identity_file'),
            user=self.params.get('remote_user'),
            strict_host_key_checking=self.params.get(
                'strict_host_key_checking'),
            user_known_hosts_file=self.params.get('user_known_hosts_file'),
            proxycommand=self.params.get('proxycommand'),
        )

        config_changed = False
        hosts_changed = []
        hosts_change_diff = []
        hosts_removed = []
        hosts_added = []

        hosts_result = [
            host for host in hosts_result if host['host'] == self.host
        ]

        if hosts_result:
            for host in hosts_result:
                if state == 'absent':
                    # Delete host from the configuration
                    config_changed = True
                    hosts_removed.append(host['host'])
                    self.config.delete_host(host['host'])
                else:
                    # Update host in the configuration
                    changed, options = self.change_host(
                        host['options'], **args)

                    if changed:
                        config_changed = True
                        self.config.update_host(host['host'], options)
                        hosts_changed.append(host['host'])
                        hosts_change_diff.append({
                            host['host']: {
                                'old': host['options'],
                                'new': options,
                            }
                        })
        elif state == 'present':
            changed, options = self.change_host(dict(), **args)

            if changed:
                config_changed = True
                hosts_added.append(self.host)
                self.config.add_host(self.host, options)

        if config_changed and not self.module.check_mode:
            try:
                self.config.write_to_ssh_config()
            except PermissionError as perm_exec:
                self.module.fail_json(
                    msg="Failed to write to %s due to permission issue: %s" %
                    (self.config_file, to_native(perm_exec)))
            # Make sure we set the permission
            perm_mode = '0600'
            if self.config_file == '/etc/ssh/ssh_config':
                perm_mode = '0644'
            self.module.set_mode_if_different(self.config_file, perm_mode,
                                              False)
            # Make sure the file is owned by the right user and group
            self.module.set_owner_if_different(self.config_file, self.user,
                                               False)
            self.module.set_group_if_different(self.config_file, self.group,
                                               False)

        self.module.exit_json(changed=config_changed,
                              hosts_changed=hosts_changed,
                              hosts_removed=hosts_removed,
                              hosts_change_diff=hosts_change_diff,
                              hosts_added=hosts_added)

    @staticmethod
    def change_host(options, **kwargs):
        options = deepcopy(options)
        changed = False
        for k, v in kwargs.items():
            if '_' in k:
                k = k.replace('_', '')

            if not v:
                if options.get(k):
                    del options[k]
                    changed = True
            elif options.get(k) != v and not (isinstance(options.get(k), list)
                                              and v in options.get(k)):
                options[k] = v
                changed = True

        return changed, options
コード例 #12
0
class DigitalOcean:
    """Automate Digital Ocean droplet deployment & management"""
    def __init__(self, api_token):
        self.api_token = api_token
        self.ssh_id = self.get_ssh_keys()
        self.ssh_config = StormParser(expanduser('~/.ssh/config'))
        self.droplet = {}
        self.droplet_attrs = [
            'name', 'disk', 'image', 'size_slug', 'ip_address'
        ]

    def update_ssh(self):
        """Update ssh config with new ip address and add missing users"""

        self.ssh_config.load()
        users = {'do': 'root', 'do2': 'kaggle'}
        for host in users.keys():
            if self.ssh_config.search_host(host):
                self.ssh_config.update_host(
                    host, {
                        'user': users[host],
                        'hostname': self.droplet['ip_address']
                    })
            else:
                self.ssh_config.add_host(host, {
                    'user': users[host],
                    'hostname': self.droplet['ip_address']
                })
        self.ssh_config.write_to_ssh_config()

    def update_config_script(self,
                             user=None,
                             password=None,
                             authorized_key='id_rsa',
                             hdf=False):
        """Make requisite substitutions in base cloud-config file"""

        with open('cloud-config.txt') as txt:
            user_data = txt.read()

        if user and password:
            user_data = user_data.replace(
                'KAGGLE_CREDENTIALS',
                '  - export KAGGLE_USER={0}\n  - export KAGGLE_PASSWD={1}'.
                format(user, password))
            download_instructions = open('download_instructions.txt').read()
            if hdf:
                download_instructions += "\n  - python3 -c 'from kaggle_data import data_to_hdf; data_to_hdf()'"
            user_data = user_data.replace('DATA_DOWNLOAD',
                                          download_instructions)

        else:
            user_data = user_data.replace('KAGGLE_CREDENTIALS', '')
            user_data = user_data.replace('DATA_DOWNLOAD', '')

        if authorized_key:
            user_data = user_data.replace(
                'SSH_AUTHORIZED_KEYS', 'ssh-authorized-keys:\n    - {}'.format(
                    open(expanduser(
                        '~/.ssh/{}.pub'.format(authorized_key))).read()))
        else:
            user_data.replace('SSH_AUTHORIZED_KEYS', '')
        return user_data

    def launch(self,
               name='kaggle-droplet',
               region='nyc2',
               image='ubuntu-16-04-x64',
               size='512mb',
               user=None,
               password=None,
               authorized_key='id_rsa',
               hdf=False):
        """Launch DigitalOcean droplet instance"""

        user_data = self.update_config_script(user=user,
                                              password=password,
                                              authorized_key=authorized_key,
                                              hdf=hdf)

        droplet = Droplet(token=self.api_token,
                          name=name,
                          region=region,
                          image=image,
                          size_slug=size,
                          backups=False,
                          ssh_keys=self.ssh_id,
                          user_data=user_data)
        droplet.create()

        self.droplet['id'] = droplet.id
        while not self.droplet.get('ip_address', None):
            self.droplet['ip_address'] = droplet.load().ip_address
        self.update_ssh()
        pprint.pprint(('Name: {}'.format(droplet.name), 'Image: {}'.format(
            droplet.image.get('slug')), 'Memory: {}'.format(droplet.size_slug),
                       'Disk Size: {}'.format(droplet.disk),
                       'IP Address: {}'.format(droplet.ip_address)))

    def get_droplets(self):
        """Get active droplets"""
        manager = Manager(token=self.api_token)
        my_droplets = manager.get_all_droplets()
        return my_droplets

    def destroy(self):
        """Destroy all active droplets"""
        my_droplets = self.get_droplets()
        for droplet in my_droplets:
            droplet.destroy()

    def get_ssh_keys(self):
        """Get ssh keys stored with DigitalOcean"""

        do_ssh_url = 'https://api.digitalocean.com/v2/account/keys'
        headers = dict(Authorization='Bearer {}'.format(self.api_token))
        response = requests.get(url=do_ssh_url, headers=headers)
        ssh_keys = []
        for ssh_key in response.json().get('ssh_keys'):
            ssh_keys.append(ssh_key.get('id'))
        return ssh_keys