Beispiel #1
0
    def build(self, update_application=False, quiet=False):
        """
        Create a virtual machine image of the configured host.

        Args:
            update_application (bool): If applicable, update the application
                definition Yaml file to use this image as host base for the
                selected provider. Warning, this will reset any yaml file
                formatting and comments.
            quiet (bool): If True, hide outputs.

        Returns:
            str: Image ID or path (Depending provider)
        """
        manifest = self._packer.build(quiet=quiet)
        image = self._packer.get_artifact(manifest)

        if update_application:
            provider = json_read(self._user_parameters_json)['provider']
            try:
                section = self._application['package'][0][provider]
            except KeyError:
                section = self._application['package'][0][provider] = dict()

            section['type'] = 'vm_image'
            section['name'] = image
            self._application.save()

        return image
Beispiel #2
0
def test_json_read_write(tmpdir):
    """
    Test json_read/json_write

    Args:
        tmpdir (py.path.local) tmpdir pytest fixture
    """
    from accelpy._common import json_write, json_read
    from accelpy.exceptions import ConfigurationException

    json_file = tmpdir.join('file.json')

    # Test: correct file
    data = {'key': 'value'}
    json_write(data, json_file)
    assert json_read(json_file) == data

    # Test: badly formatted file
    json_file.write('{key: ')
    with pytest.raises(ConfigurationException):
        json_read(json_file)
Beispiel #3
0
    def _get_last_version(cls):
        """
        Get last version information from HashiCorp checkpoint API.

        Returns:
            dict: Last version information.
        """
        info_cache = join(cls._install_dir(), 'info.json')

        # Get Last version information from HashiCorp checkpoint API
        if not isfile(info_cache) or getmtime(info_cache) < time() - 3600.0:

            # Lazy import: Only used on update
            from platform import machine, system

            # Update from the web
            last_release = cls._download(
                'https://checkpoint-api.hashicorp.com/v1/check/' +
                cls._name()).json()

            current_version = last_release['current_version']
            download_url = last_release['current_download_url'].rstrip('/')

            # Define platform specific utility executable and archive name
            arch = machine().lower()
            arch = {'x86_64': 'amd64'}.get(arch, arch)

            last_release['archive_name'] = archive_name = \
                f"{cls._name()}_{current_version}_{system().lower()}_{arch}.zip"

            last_release['executable_name'] = \
                f'{cls._name()}.exe' if system() == 'Windows' else cls._name()

            # Define download URL
            last_release['archive_url'] = f"{download_url}/{archive_name}"
            last_release['checksum_url'] = checksum_url = \
                f"{download_url}/{cls._name()}_{current_version}_SHA256SUMS"
            last_release['signature_url'] = f"{checksum_url}.sig"

            # Cache result
            makedirs(cls._install_dir(), exist_ok=True)
            json_write(last_release, info_cache)

        else:
            # Get cached version
            last_release = json_read(info_cache)

        return last_release
Beispiel #4
0
    def create_configuration(self, provider=None, application_type=None,
                             variables=None, user_config=None):
        """
        Generate packer configuration file.

        Args:
            provider (str): Provider name.
            user_config (path-like object): User configuration directory.
            vars (dict): Terraform input variables.
        """
        # Lazy import, may not be used
        from jinja2 import Environment

        # Get template from this package and user directories
        sources = dict(vars=dict(variables=variables or dict()))

        for name, src_path in self._list_sources(
                provider, application_type, user_config):
            sources[name] = json_read(src_path)

        # Generate the Packer template file
        template = dict()
        for key in sorted(sources):
            recursive_update(template, sources[key])

        # Evaluate variables that contain Jinja templates
        variables = template['variables']
        env = Environment(extensions=['jinja2.ext.loopcontrols'])
        to_clean = set()
        for key in sorted(variables):
            value = variables[key]
            if isinstance(value, str) and '{' in value:
                variables[key] = env.from_string(value).render(variables)

            # Mark for deletion, Packer does not accept non string as variables
            elif not isinstance(value, str):
                to_clean.add(key)

        for key in to_clean:
            del variables[key]

        # Save template
        json_write(template, self._template)
Beispiel #5
0
    def create_configuration(self):
        """
        Generate packer configuration file.
        """
        # Lazy import: Only used on new configuration creation
        from accelpy._ansible import Ansible

        # Get template from this package and user directories
        self._variables['ansible'] = Ansible.playbook_exec()
        sources = dict(vars=dict(variables=self._variables))

        for name, src_path in self._list_sources():
            sources[name] = json_read(src_path)

        # Generate the Packer template file
        template = dict()
        for key in sorted(sources):
            recursive_update(template, sources[key])

        json_write(template, self._template)
Beispiel #6
0
    def build(self, quiet=False):
        """
        Build image.

        Args:
            quiet (bool): If True, hide outputs.

        Returns:
            dict: Packer manifest (Last build only).
        """
        # Build
        self._exec('build', '-color=false', self._template, pipe_stdout=quiet)

        # Read manifest file
        manifest = json_read(join(self._config_dir, 'packer-manifest.json'))
        last_run_uuid = manifest['last_run_uuid']
        for build in manifest['builds']:
            if build['packer_run_uuid'] == last_run_uuid:
                return build
        else:
            # Should never raise
            raise RuntimeError(
                f'No packer manifest for run with UUID {last_run_uuid}')
Beispiel #7
0
    def __init__(self,
                 name=None,
                 application=None,
                 provider=None,
                 user_config=None,
                 destroy_on_exit=False,
                 keep_config=True):

        # Initialize some futures values
        self._ansible_config = None
        self._packer_config = None
        self._terraform_config = None
        self._terraform_output = None
        self._application_definition = None

        # If true, Terraform infrastructure is destroyed on exit
        self._destroy_on_exit = destroy_on_exit
        self._keep_config = keep_config

        # Define name
        if not name:
            from uuid import uuid1
            name = str(uuid1()).replace('-', '')
        self._name = name

        # Define configuration directory en files
        self._config_dir = join(CONFIG_DIR, name)
        user_parameters_json = join(self._config_dir, 'user_parameters.json')
        self._output_json = join(self._config_dir, 'output.json')
        self._accelize_drm_conf_json = join(self._config_dir,
                                            'accelize_drm_conf.json')
        self._accelize_drm_cred_json = join(self._config_dir, 'cred.json')

        # Create a new configuration
        config_exists = isdir(self._config_dir)
        if not config_exists and application:

            # Ensure config is cleaned on creation error
            self._keep_config = False

            # Create target configuration directory and remove access to other
            # users since Terraform state files may content sensible data and
            # directory may contain SSH private key
            makedirs(self._config_dir, exist_ok=True)
            chmod(self._config_dir, 0o700)

            # Get user parameters used
            self._provider = provider
            self._user_config = fsdecode(user_config or HOME_DIR)

            # Save user parameters
            json_write(
                dict(provider=self._provider, user_config=self._user_config),
                user_parameters_json)

            # Get application and add it as link with configuration
            self._application_yaml = realpath(fsdecode(application))

            # Check Accelize Requirements
            self._init_accelize_drm()

            # Add link to configuration
            symlink(self._application_yaml,
                    join(self._config_dir, 'application.yml'))

            # Initialize Terraform and Ansible configuration
            self._terraform.create_configuration()
            self._ansible.create_configuration()
            self._packer.create_configuration()

            self._keep_config = keep_config

        # Load an existing configuration
        elif config_exists:

            # Retrieve application parameters
            self._application_yaml = realpath(
                join(self._config_dir, 'application.yml'))

            # Retrieve user parameters
            user_parameters = json_read(user_parameters_json)
            self._provider = user_parameters['provider']
            self._user_config = user_parameters['user_config']

        # Unable to create configuration
        else:
            raise ConfigurationException(
                'Require at least an existing host name, or an '
                'application to create a new host.')