Skip to content

Commit

Permalink
refactor(JOBS): extract class hierarchy
Browse files Browse the repository at this point in the history
  • Loading branch information
niall-byrne committed Jan 14, 2022
1 parent 3e12767 commit 67e553c
Show file tree
Hide file tree
Showing 15 changed files with 557 additions and 501 deletions.
1 change: 1 addition & 0 deletions documentation/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"mac_maker.tests",
"mac_maker.ansible_controller.tests",
"mac_maker.commands.tests",
"mac_maker.jobs.tests",
"mac_maker.utilities.tests",
]

Expand Down
1 change: 1 addition & 0 deletions mac_maker/ansible_controller/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ def _perform_clean_exit(self) -> None:
sys.exit(0)
raise ClickShellCleanExit()

# TODO: Move into CLI module?
def _was_started_without_shell(self) -> bool:
for command in cli.cli.commands.keys():
if command in sys.argv:
Expand Down
24 changes: 11 additions & 13 deletions mac_maker/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import click
from click_shell import shell
from .commands.version import VersionCommand
from .jobs import Jobs
from .jobs import filesystem_job, github_job
from .utilities.logger import Logger


Expand Down Expand Up @@ -44,9 +44,8 @@ def check_from_github(github_url: str, branch: Optional[str]) -> None:
GITHUB_URL: URL of a GitHub repo containing a machine profile definition.
"""
job = Jobs()
precheck_data = job.get_precheck_content_from_github(github_url, branch)
job.precheck(precheck_data)
job = github_job.GitHubJob(github_url, branch)
job.precheck()


@precheck.command("spec") # type: ignore[misc]
Expand All @@ -56,9 +55,8 @@ def check_from_spec(spec_file: str) -> None:
SPEC_FILE: The location of a spec.json file referencing a profile.
"""
job = Jobs()
precheck_data = job.get_precheck_content_from_spec(spec_file)
job.precheck(precheck_data)
job = filesystem_job.FileSystemJob(spec_file)
job.precheck()


@apply.command("github") # type: ignore[misc]
Expand All @@ -74,9 +72,9 @@ def apply_from_github(github_url: str, branch: Optional[str]) -> None:
GITHUB_URL: URL of a GitHub repo containing a machine profile definition.
"""
job = Jobs()
job_spec = job.create_state_from_github_spec(github_url, branch)
job.provision(job_spec)
job = github_job.GitHubJob(github_url, branch)
job.precheck()
job.provision()


@apply.command("spec") # type: ignore[misc]
Expand All @@ -86,9 +84,9 @@ def apply_from_spec(spec_file: str) -> None:
SPEC_FILE: The location of a spec.json file.
"""
job = Jobs()
job_spec = job.create_state_from_local_spec_file(spec_file)
job.provision(job_spec)
job = filesystem_job.FileSystemJob(spec_file)
job.precheck()
job.provision()


@cli.command("version") # type: ignore[misc]
Expand Down
125 changes: 0 additions & 125 deletions mac_maker/jobs.py

This file was deleted.

Empty file added mac_maker/jobs/__init__.py
Empty file.
57 changes: 57 additions & 0 deletions mac_maker/jobs/bases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""Job base classes for the Mac Maker."""

import abc
import sys

import click
from ..ansible_controller.inventory import InventoryFile
from ..ansible_controller.runner import AnsibleRunner
from ..utilities.password import SUDO
from ..utilities.precheck import PrecheckConfig, TypePrecheckFileData
from ..utilities.spec import JobSpec
from ..utilities.state import TypeState


class JobBase(abc.ABC):
"""Job base class for the Mac Maker."""

def __init__(self) -> None:
self.jobspec = JobSpec()

@abc.abstractmethod
def get_precheck_content(self) -> TypePrecheckFileData:
"""Extract the profile's precheck file contents."""
raise NotImplementedError # nocover

@abc.abstractmethod
def get_state(self) -> TypeState:
"""Assemble and return a state object."""
raise NotImplementedError # nocover

def precheck(self) -> None:
"""Precheck the profile for validity and environment variable content."""

precheck_data = self.get_precheck_content()

validator = PrecheckConfig(precheck_data['env'])
validator.is_valid_env_file()
results = validator.validate_environment()
if not results['is_valid']:
for violation in results['violations']:
click.echo(violation)
sys.exit(1)
click.echo(precheck_data['notes'])

def provision(self) -> None:
"""Begin provisioning the local machine."""

loaded_state = self.get_state()

sudo = SUDO()
sudo.prompt_for_sudo()

inventory = InventoryFile(loaded_state)
inventory.write_inventory_file()

ansible_job = AnsibleRunner(loaded_state)
ansible_job.start()
44 changes: 44 additions & 0 deletions mac_maker/jobs/filesystem_job.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""A provisioning job for a spec file and profile on the local file system."""

import click
from .. import config
from ..utilities.precheck import TypePrecheckFileData
from ..utilities.state import TypeState
from . import bases


class FileSystemJob(bases.JobBase):
"""A provisioning job for a spec file and profile on the local file system.
:param spec_file_location: The path to the spec file.
"""

spec_file_location: str

def __init__(self, spec_file_location: str):
super().__init__()
self.spec_file_location = spec_file_location

def get_precheck_content(self) -> TypePrecheckFileData:
"""Read the precheck data using a spec file.
:returns: The precheck file data.
"""

precheck_data = self.jobspec.extract_precheck_from_job_spec(
self.spec_file_location
)
return precheck_data

def get_state(self) -> TypeState:
"""Read a spec file from the filesystem and build a state object.
:returns: The created state object.
"""

job_spec = self.jobspec.create_job_spec_from_filesystem(
self.spec_file_location
)
click.echo(config.ANSIBLE_JOB_SPEC_READ_MESSAGE)
click.echo(job_spec['spec_file_location'])
return job_spec['spec_file_content']
63 changes: 63 additions & 0 deletions mac_maker/jobs/github_job.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""A provisioning job for a profile in a Github repository."""

from typing import Optional, cast

import click
from .. import config
from ..utilities.github import GithubRepository
from ..utilities.precheck import TypePrecheckFileData
from ..utilities.state import TypeState
from ..utilities.workspace import WorkSpace
from . import bases


class GitHubJob(bases.JobBase):
"""A provisioning job for a profile in a Github repository.
:param repository_url: The GitHub Repository URL.
:param branch_name: The GitHub Repository branch name.
"""

repository_url: str
branch_name: Optional[str]

def __init__(self, repository_url: str, branch_name: Optional[str]):
super().__init__()
self.repository_url = repository_url
self.branch_name = branch_name

def get_precheck_content(self) -> TypePrecheckFileData:
"""Read the precheck data from a GitHub repository.
:returns: The precheck file data.
"""

repo = GithubRepository(self.repository_url)
precheck_data = repo.download_zip_bundle_files(
self.branch_name,
{
'notes': str(config.PRECHECK['notes']),
'env': str(config.PRECHECK['env']),
},
)
return cast(TypePrecheckFileData, precheck_data)

def get_state(self) -> TypeState:
"""Fetch a GitHub zip bundle, and build a state object.
:returns: The created state object.
"""

click.echo(config.ANSIBLE_RETRIEVE_MESSAGE)

repo = GithubRepository(self.repository_url)

workspace = WorkSpace()
workspace.add_repository(repo, self.branch_name)

repo.download_zip_bundle_profile(workspace.root, self.branch_name)
job_spec = self.jobspec.create_job_spec_from_github(workspace)

click.echo(config.ANSIBLE_JOB_SPEC_MESSAGE)
click.echo(job_spec['spec_file_location'])
return job_spec['spec_file_content']
Empty file.
Loading

0 comments on commit 67e553c

Please sign in to comment.