Skip to content

Commit

Permalink
Compute the bgp_layout rather than relying on charm-config (#3)
Browse files Browse the repository at this point in the history
* Adjust setup.sh to allow for local development

* use the calico-enteprise peer relation to compute bpg_parameters rather than requiring it as config

* py38 linting
  • Loading branch information
addyess authored Oct 24, 2023
1 parent d31ac17 commit 5fa828e
Show file tree
Hide file tree
Showing 13 changed files with 584 additions and 214 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ __pycache__/

# terraform metadata
.terraform/
*.terraform.lock.hcl
*.tfstate*
.integration_local_env
78 changes: 27 additions & 51 deletions src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from ops.framework import StoredState
from ops.main import main
from ops.model import ActiveStatus, BlockedStatus, MaintenanceStatus, StatusBase, WaitingStatus
from peer import CalicoEnterprisePeer

VALID_LOG_LEVELS = ["info", "debug", "warning", "error", "critical"]

Expand Down Expand Up @@ -70,7 +71,7 @@ def __init__(self, code, message="Error with Tigera"):
super().__init__(self.message)


class TigeraCharm(CharmBase):
class CalicoEnterpriseCharm(CharmBase):
"""Charm the Tigera Calico EE."""

stored = StoredState()
Expand All @@ -85,14 +86,16 @@ def __init__(self, *args):
self.framework.observe(self.on.upgrade_charm, self.on_upgrade_charm)
self.framework.observe(self.on.cni_relation_joined, self.on_cni_relation_joined)
self.framework.observe(self.on.cni_relation_changed, self.on_cni_relation_changed)
self.framework.observe(self.on.calico_enterprise_relation_changed, self.on_config_changed)
self.framework.observe(self.on.start, self.on_config_changed)
self.framework.observe(self.on.upgrade_charm, self.on_config_changed)

self.stored.set_default(tigera_configured=False)
self.stored.set_default(pod_restart_needed=False)
self.stored.set_default(tigera_cni_configured=False)

self.peers = CalicoEnterprisePeer(self)
self.framework.observe(self.peers.on.bgp_parameters_changed, self.on_config_changed)

# try:
# self.CTL = getContainerRuntimeCtl()
# except RuntimeError:
Expand Down Expand Up @@ -155,28 +158,10 @@ def render_template(self, template_file, destination, **kwargs):
template.stream(**kwargs).dump(destination)
return destination

def calico_enterprise_peer_data(self, key):
"""Return the agreed data associated with the key from each calico-enterprise unit including self.
If there isn't unity in the relation, return None.
"""
joined_data = set()
for relation in self.model.relations["calico-enterprise"]:
for unit in relation.units | {self.unit}:
data = relation.data[unit].get(key)
joined_data.add(data)
filtered = set(filter(bool, joined_data))
return filtered.pop() if len(filtered) == 1 else None

def get_ip_range(self, n):
"""Return the # of bits that compose its range from an IPAddress."""
return str(n).split("/")[1]

@property
def bgp_parameters(self):
"""Return bgp parameter as a dict."""
return yaml.safe_load(self.model.config["bgp_parameters"])

def image_registry_secret(self) -> Tuple[Optional[RegistrySecret], str]:
"""Read Image Registry secret to username:password."""
value = self.model.config["image_registry_secret"]
Expand All @@ -203,7 +188,7 @@ def preflight_checks(self):
Returns True if successful on all checks pass, False otherwise.
"""
if not self.model.config["bgp_parameters"]:
if not self.peers.bgp_layout.nodes:
self.unit.status = BlockedStatus("BGP configuration is required.")
return False

Expand Down Expand Up @@ -356,18 +341,12 @@ def implement_early_network(self):
2) deploy cnx-node systemd
3) wait until cnx-node is listening on port 8179
"""
## TODO: implement the early_network
## ...
os.makedirs("/calico-early/", exist_ok=True)
self.render_template(
"templates/calico_bgp_layout.yaml.j2",
"/calico-early/cfg.yaml",
bgp_parameters=self.config["bgp_parameters"],
)
self.peers.bgp_layout # TODO implement the early_network

def waiting_for_cni_relation(self):
"""Check if we should wait on CNI relation or all data is available."""
service_cidr = self.calico_enterprise_peer_data("service-cidr")
service_cidr = self.peers.service_cidr
registry = self.registry
return not self.is_kubeconfig_available() or not service_cidr or not registry

Expand All @@ -376,30 +355,30 @@ def pre_tigera_init_config(self):
if not pathlib.Path(KUBECONFIG_PATH).exists():
self.unit.status = BlockedStatus("Waiting for Kubeconfig to become available")
return False
bgp_parameters = self.model.config["bgp_parameters"]

try:
self.kubectl("create", "ns", "tigera-operator")
self.kubectl("create", "ns", "calico-system")
except CalledProcessError:
pass
if not bgp_parameters:
self.unit.status = BlockedStatus("bgp_parameters is required.")
if not self.peers.bgp_layout.nodes:
self.unit.status = WaitingStatus("bgp_parameters is required.")
return False

for node in yaml.safe_load(bgp_parameters):
for node in self.peers.bgp_layout.nodes:
hostname = node.hostname
if not hostname:
continue
rack = node.labels.rack
try:
self.kubectl("label", "node", node["hostname"], f"rack={node['rack']}")
self.kubectl("label", "node", hostname, f"rack={rack}")
except CalledProcessError:
log.warning(f"Node labelling failed. Does {node['hostname']} exist?")
log.warning(f"Node labelling failed. Does {hostname} exist?")
pass

self.render_template(
"bgp_layout.yaml.j2",
"/tmp/bgp_layout.yaml",
bgp_parameters=self.bgp_parameters,
)
self.kubectl("apply", "-n", "tigera-operator", "-f", "/tmp/bgp_layout.yaml")
# self.kubectl("apply", "-n", "calico-system", "-f", "/tmp/bgp_layout.yaml")
with tempfile.NamedTemporaryFile("w") as bgp_layout:
yaml.safe_dump(self.peers.bgp_layout_config_map, stream=bgp_layout)
self.kubectl("apply", "-n", "tigera-operator", "-f", bgp_layout.name)

return True

Expand All @@ -422,7 +401,7 @@ def configure_bgp(self):
self.render_template(
"bgppeer.yaml.j2",
"/tmp/bgppeer.yaml",
bgp_parameters=self.bgp_parameters,
peer_set=self.peers.bgp_peer_set,
)
self.kubectl("apply", "-n", "tigera-operator", "-f", "/tmp/bgppeer.yaml")
self.render_template(
Expand Down Expand Up @@ -522,7 +501,6 @@ def on_config_changed(self, event): # noqa C901, TODO: consider using reconcile
# TODO: Enters a defer loop
# event.defer()
return
service_cidr = self.calico_enterprise_peer_data("service-cidr")

if self.waiting_for_cni_relation():
self.unit.status = WaitingStatus("Waiting for CNI relation")
Expand Down Expand Up @@ -598,13 +576,11 @@ def on_config_changed(self, event): # noqa C901, TODO: consider using reconcile
image_prefix=self.model.config["image_prefix"],
nic_autodetection=nic_autodetection,
)
self.render_template(
"bgpconfiguration.yaml.j2",
"/tmp/calico_bgp_configuration.yaml",
service_cidr=service_cidr,
)
self.kubectl("apply", "-f", "/tmp/calico_enterprise_install.yaml")
self.kubectl("apply", "-f", "/tmp/calico_bgp_configuration.yaml")

with tempfile.NamedTemporaryFile("w") as bgp_configuration:
yaml.safe_dump(self.peers.bgp_configuration, stream=bgp_configuration)
self.kubectl("apply", "-f", bgp_configuration.name)

if self.model.config["addons"]:
self.unit.status = MaintenanceStatus("Applying Addons")
Expand All @@ -625,4 +601,4 @@ def on_config_changed(self, event): # noqa C901, TODO: consider using reconcile


if __name__ == "__main__": # pragma: nocover
main(TigeraCharm)
main(CalicoEnterpriseCharm)
Loading

0 comments on commit 5fa828e

Please sign in to comment.