Skip to content

Commit

Permalink
feat(ENVIRONMENT): class to manage runtime env
Browse files Browse the repository at this point in the history
  • Loading branch information
niall-byrne committed Jun 10, 2021
1 parent b8bb14c commit 428752a
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 0 deletions.
49 changes: 49 additions & 0 deletions mac_maker/ansible_controller/environment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""Ansible runtime environment class."""

import logging
import os
from typing import Dict

from .. import config


class Environment:

def __init__(self, state: dict):
self.log = logging.getLogger(config.LOGGER_NAME)
self.env: Dict[str, str] = {}
self.state = state

def setup(self):
self.log.debug(
"Environment: configuring Ansible runtime environment variables..."
)

self.combine_env_with_state(config.ENV_ANSIBLE_ROLES_PATH, 'roles_path')
self.combine_env_with_state(
config.ENV_ANSIBLE_COLLECTIONS_PATH, 'collections_path'
)
self._save()
self.log.debug("Environment: Ansible runtime environment is ready.")

def combine_env_with_state(self, variable_name: str, state_name: str):
existing_env_value = self._env_to_list(variable_name)
existing_state_value = self._state_to_list(state_name)
new_env_value = existing_state_value + existing_env_value
self.env[variable_name] = self._list_to_env(new_env_value)

def _env_to_list(self, variable_name: str) -> list:
value = os.getenv(variable_name, None)
if value is None:
return []
return value.split(":")

def _state_to_list(self, state_name: str) -> list:
return self.state[state_name]

def _list_to_env(self, list_content: list) -> str:
return ":".join(list_content)

def _save(self):
for key, value in self.env.items():
os.environ[key] = value
102 changes: 102 additions & 0 deletions mac_maker/ansible_controller/tests/test_environment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
"""Test the Environment class."""
import os
from logging import Logger
from unittest import TestCase, mock

from ...utilities import filesystem, state
from .. import environment

ENV_MODULE = environment.__name__


def mock_environment(**environment_variables):
return mock.patch.dict(os.environ, environment_variables)


class TestEnvironmentClass(TestCase):
"""Test the Environment class."""

def setUp(self):
self.mock_root = ""
self.filesystem = filesystem.FileSystem(self.mock_root)
self.state = state.State()
self.mock_state = self.state.state_generate(self.filesystem)
self.environment = environment.Environment(self.mock_state)

def test_init(self):

self.assertIsInstance(
self.environment.log,
Logger,
)
self.assertEqual(
self.environment.state,
self.state.state_generate(self.filesystem),
)
self.assertDictEqual(
self.environment.env,
{},
)

@mock_environment()
def test_setup_clean_environment(self):

self.environment.setup()

self.assertDictEqual(
self.environment.env, {
'ANSIBLE_ROLES_PATH': self.mock_state['roles_path'][0],
'ANSIBLE_COLLECTIONS_PATH': self.mock_state['collections_path'][0],
}
)

for key, value in self.environment.env.items():
self.assertEqual(os.environ[key], value)

@mock_environment()
def test_setup_clean_environment_multiple(self):
self.mock_state['roles_path'].append('/non/existent/1')
self.mock_state['collections_path'].append('/non/existent/2')

self.environment.setup()

self.assertDictEqual(
self.environment.env, {
'ANSIBLE_ROLES_PATH':
":".join(self.mock_state['roles_path']),
'ANSIBLE_COLLECTIONS_PATH':
":".join(self.mock_state['collections_path']),
}
)

for key, value in self.environment.env.items():
self.assertEqual(os.environ[key], value)

@mock_environment(
ANSIBLE_ROLES_PATH='/non/existent/01:/non/existent/02',
ANSIBLE_COLLECTIONS_PATH='/non/existent/03:/non/existent/04',
)
def test_setup_clean_environment_existing(self):
self.environment.setup()

self.assertDictEqual(
self.environment.env, {
'ANSIBLE_ROLES_PATH':
":".join(
self.mock_state['roles_path'] + [
'/non/existent/01',
'/non/existent/02',
]
),
'ANSIBLE_COLLECTIONS_PATH':
":".join(
self.mock_state['collections_path'] + [
'/non/existent/03',
'/non/existent/04',
]
),
}
)

for key, value in self.environment.env.items():
self.assertEqual(os.environ[key], value)
1 change: 1 addition & 0 deletions mac_maker/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

ENV_ANSIBLE_BECOME_PASSWORD = "ANSIBLE_BECOME_PASSWORD"
ENV_ANSIBLE_ROLES_PATH = "ANSIBLE_ROLES_PATH"
ENV_ANSIBLE_COLLECTIONS_PATH = "ANSIBLE_COLLECTIONS_PATH"

ANSIBLE_INVOKE_MESSAGE = "--- Invoking Ansible Runner ---"
ANSIBLE_INVENTORY_CONTENT = (
Expand Down

0 comments on commit 428752a

Please sign in to comment.