Skip to content
This repository has been archived by the owner on Jul 30, 2024. It is now read-only.

Update from prior work #19

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
65 changes: 65 additions & 0 deletions examples/invalid-bad_hostname.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
network:
port_forward:
- SSH to Bastion
- HTTPS to Cluster API
- HTTP to Cluster Apps
- HTTPS to Cluster Apps
- HTTPS to Cockpit Panel
lan:
subnet: 192.168.8.0/24
interfaces:
- eno1
- eno5
dns_forward_resolvers:
- 10.1.1.1
dhcp:
ignore_macs:
- name: node-0-eno1
mac: da:d5:de:ad:be:ef
- name: node-0-eno2
mac: da:d5:de:ad:be:ef
- name: node-0-eno3
mac: da:d5:de:ad:be:ef
extra_reservations:
- name: wifi
mac: da:d5:de:ad:be:ef
ip: 192.168.8.127
- name: chassis
mac: da:d5:de:ad:be:ef
ip: 192.168.8.50
- name: bastion-ilo
mac: da:d5:de:ad:be:ef
ip: 192.168.8.51
- name: client
mac: da:d5:de:ad:be:ef
ip: 192.168.8.52
bastion:
become_pass: <ultrasecret>
cluster:
pull_secret: '{"auths":{"cloud.openshift.com":{"auth":"sometoken","email":"[email protected]"}}}' # etc
management:
provider: ilo
user: Administrator
password: <ultrasecret>
nodes:
- name: node 1
mac: da:d5:de:ad:be:ef
mgmt_mac: fe:eb:da:ed:5d:ad
- name: node 2
mac: da:d5:de:ad:be:ef
mgmt_mac: fe:eb:da:ed:5d:ad
- name: node 3
mac: da:d5:de:ad:be:ef
mgmt_mac: fe:eb:da:ed:5d:ad
proxy:
http: proxy.faros.site
https: secure-proxy.faros.site
noproxy:
- registry.access.redhat.com
ca: |
# Proxy Server Certificate
-----BEGIN CERTIFICATE-----
MIIGlTCCBH2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjjELMAkGA1UEBhMCVVMx
...
epmW5U8YK4yf
-----END CERTIFICATE----
43 changes: 43 additions & 0 deletions examples/invalid-no_dhcp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
network:
port_forward:
- SSH to Bastion
lan:
subnet: 192.168.8.0/24
interfaces: []
dhcp:
ignore_macs:
- name: node-0-eno1
mac: da:d5:de:ad:be:ef
- name: node-0-eno2
mac: da:d5:de:ad:be:ef
- name: node-0-eno3
mac: da:d5:de:ad:be:ef
extra_reservations:
- name: wifi
mac: da:d5:de:ad:be:ef
ip: 192.168.8.127
- name: chassis
mac: da:d5:de:ad:be:ef
ip: 192.168.8.50
- name: bastion-ilo
mac: da:d5:de:ad:be:ef
ip: 192.168.8.51
- name: client
mac: da:d5:de:ad:be:ef
ip: 192.168.8.52
bastion:
become_pass: admin
cluster:
pull_secret: ''
management:
provider: ilo
user: Administrator
password: ilo-pass
nodes:
# Not 3 nodes
- name: node-0
mac: ff:ff:ff:ff:ff:ff
mgmt_mac: ff:ff:ff:ff:ff:ff
- name: node-1
mac: ff:ff:ff:ff:ff:ff
mgmt_mac: ff:ff:ff:ff:ff:ff
14 changes: 10 additions & 4 deletions src/faros_config/bastion.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@
includes settings specific to the bastion host itself.
"""

from pydantic import BaseModel
from pydantic import Field

from .common import FarosBaseModel

class BastionConfig(BaseModel):
"""The Bastion config section model."""

become_pass: str
class BastionConfig(FarosBaseModel):
"""Configuration specific to the bastion host."""

become_pass: str = Field(
alias="Sudo Password",
description=("The password for the sudo user executing Faros on the "
"bastion.")
)
76 changes: 58 additions & 18 deletions src/faros_config/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,78 @@
This module contains the configuration models for the cluster section. This
includes configuration of cluster-node specific information.
"""
from pydantic import BaseModel
from pydantic import Field, validator
from typing import List, Optional

from .common import MacAddress, StrEnum
from .common import FarosBaseModel, HostName, MacAddress, StrEnum


class ManagementProviderItem(StrEnum):
"""The supported management providers."""

ILO = "ilo"
iLO = "ilo"


class ManagementConfig(BaseModel):
"""The config model for the cluster node management."""
class ManagementConfig(FarosBaseModel):
"""Configuration for management of bare metal nodes."""

provider: ManagementProviderItem
user: str
password: str
provider: ManagementProviderItem = Field(
ManagementProviderItem("ilo"),
alias="Management Provider",
description="The management provider for this cluster."
)
user: str = Field(
alias="Management Username",
description="The username for the management provider."
)
password: str = Field(
alias="Management Password",
description="The password for the management provider."
)


class NodeConfig(BaseModel):
"""The config model for cluster nodes themselves."""
class NodeConfig(FarosBaseModel):
"""Configuration for Faros cluster nodes."""

name: str
mac: MacAddress
mgmt_mac: MacAddress
install_drive: Optional[str]
name: HostName = Field(
alias="Node Hostname",
description="A DNS-compliant friendly name for the node."
)
mac: MacAddress = Field(
alias="Node MAC Address",
description=("The MAC address of the node that should be used for PXE "
"and cluster networking.")
)
mgmt_mac: MacAddress = Field(
alias="Node Management MAC Address",
description="The MAC address of the management interface for the node."
)
install_drive: Optional[str] = Field(
alias="Node Installation Drive",
description="The device path for the drive to install CoreOS onto."
)


class ClusterConfig(BaseModel):
class ClusterConfig(FarosBaseModel):
"""The cluster config section model."""

pull_secret: str
management: ManagementConfig
nodes: List[NodeConfig]
pull_secret: str = Field(
alias="Pull Secret",
description=("The Red Hat pull secret for OpenShift installation, "
"acquired from https://cloud.redhat.com.")
)
management: ManagementConfig = Field(
alias="Management Configuration",
description="Configuration for management of bare metal nodes."
)
nodes: List[NodeConfig] = Field(
alias="Node Configuration",
description="Configuration for Faros cluster nodes."
)

@validator('nodes')
def exactly_three_nodes(cls, v):
"""Confirm that we are building a cluster of three nodes."""
if len(v) != 3:
raise ValueError('must have exactly three nodes')
return v
19 changes: 18 additions & 1 deletion src/faros_config/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from enum import Enum
from pydantic import constr, BaseModel

HostName = constr(regex=r'^(?![0-9]+$)(?!-)[a-zA-Z0-9-]{,63}(?<!-)$')
MacAddress = constr(regex=r'(([0-9A-Fa-f]{2}[-:]){5}[0-9A-Fa-f]{2})|(([0-9A-Fa-f]{4}\.){2}[0-9A-Fa-f]{4})') # noqa: E501


Expand All @@ -16,7 +17,23 @@ class StrEnum(str, Enum):
A mix-in of string and enum, representing itself as the string value.
"""

pass
@classmethod
def list(cls) -> list:
"""Return a list of the available options in the Enum."""
return [e.value for e in cls]

def __str__(self) -> str:
"""Return only the value of the enum when cast to String."""
return self.value


class FarosBaseModel(BaseModel):
"""Faros Base Model for configuration classes."""

class Config:
"""Configuration class for Pydantic models."""

allow_population_by_field_name = True


class PydanticEncoder(json.JSONEncoder):
Expand Down
26 changes: 19 additions & 7 deletions src/faros_config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,36 @@
This module contains the top level configuration model for Project Faros.
"""
import json
from pydantic import BaseModel
from pydantic import Field
from typing import Optional
import yaml

from .bastion import BastionConfig
from .cluster import ClusterConfig
from .common import PydanticEncoder
from .common import FarosBaseModel, PydanticEncoder
from .network import NetworkConfig
from .proxy import ProxyConfig


class FarosConfig(BaseModel):
class FarosConfig(FarosBaseModel):
"""Validate, serialize, and deserialize Faros configurations."""

network: NetworkConfig
bastion: BastionConfig
cluster: ClusterConfig
proxy: Optional[ProxyConfig]
network: NetworkConfig = Field(
alias="Network Configuration",
description="Configuration of the FarosLAN and WAN networks."
)
bastion: BastionConfig = Field(
alias="Bastion Configuration",
description="Configuration of bastion-specific settings."
)
cluster: ClusterConfig = Field(
alias="Cluster Configuration",
description="Configuration of cluster settings related to the nodes."
)
proxy: Optional[ProxyConfig] = Field(
alias="Proxy Configuration",
description="Configuration of HTTP/S proxy settings for the cluster."
)

@classmethod
def from_yaml(cls, yaml_file: str) -> 'FarosConfig':
Expand Down
Loading