Ejemplo n.º 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
Ejemplo n.º 2
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
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
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