Skip to content

Commit

Permalink
Starter implementation to write containerd hosts.tomls (#122)
Browse files Browse the repository at this point in the history
* Starter implementation to write containerd hosts.tomls

* Share custom-registries config via a containerd relation

* Unit tests for containerd

* Create unit test temp files in

* write toml to conf.d/ to escape unnecessary containerd restart

* Rewrite auth support
  • Loading branch information
addyess authored Jun 21, 2024
1 parent 238f42a commit 54dc67e
Show file tree
Hide file tree
Showing 8 changed files with 601 additions and 2 deletions.
2 changes: 2 additions & 0 deletions charms/worker/charmcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,5 @@ requires:
# juju integrate k8s:k8s-cluster k8s-worker:cluster
cos-tokens:
interface: cos-k8s-tokens
containerd:
interface: containerd
49 changes: 49 additions & 0 deletions charms/worker/k8s/charmcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,53 @@ bases:
architectures: [amd64]
config:
options:
containerd_custom_registries:
type: string
default: "[]"
description: |
Registry endpoints and credentials. Setting this config allows containerd
to pull images from registries where auth is required.
The value for this config must be a JSON array of credential objects, like this:
e.g.: [{"url": "https://registry.example.com", "host": "my.registry:port", "username": "user", "password": "pass"}]
Credential Object Parameters:
url: REQUIRED str
the URL to the registry, include the port if not it isn't implied from the schema.
e.g: "url": "https://my.registry:8443"
e.g: "url": "http://my.registry"
host: OPTIONAL str - defaults to auto-generated from the url
could be registry host address or a name
e.g.: myregistry.io:9000, 10.10.10.10:5432
e.g.: myregistry.io, myregistry
Note: It will be derived from `url` if not provided.
e.g.: "url": "http://10.10.10.10:8000" --> "host": "10.10.10.10:8000"
username: OPTIONAL str - default ''
password: OPTIONAL str - default ''
identitytoken: OPTIONAL str - default ''
Used by containerd for basic authentication to the registry.
ca_file: OPTIONAL str - default ''
cert_file: OPTIONAL str - default ''
key_file: OPTIONAL str - default ''
For ssl/tls communication these should be a base64 encoded file
e.g.: "ca_file": "'"$(base64 -w 0 < my.custom.registry.pem)"'"
skip_verify: OPTIONAL bool - default false
For situations where the registry has self-signed or expired certs and a quick work-around is necessary.
e.g.: "skip_verify": true
example config)
juju config containerd custom_registries='[{
"url": "https://registry.example.com",
"host": "ghcr.io",
"ca_file": "'"$(base64 -w 0 < ~/my.custom.ca.pem)"'",
"cert_file": "'"$(base64 -w 0 < ~/my.custom.cert.pem)"'",
"key_file": "'"$(base64 -w 0 < ~/my.custom.key.pem)"'",
}]'
datastore:
default: dqlite
type: string
Expand Down Expand Up @@ -113,6 +160,8 @@ provides:
interface: k8s-cluster
cos-worker-tokens:
interface: cos-k8s-tokens
containerd:
interface: containerd

requires:
etcd:
Expand Down
2 changes: 2 additions & 0 deletions charms/worker/k8s/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ cosl==0.0.8
ops==2.14.0
pydantic==1.10.15
PyYAML==6.0.1
tomli == 2.0.1
tomli-w == 1.0.0
typing_extensions==4.12.0
websocket-client==1.8.0
22 changes: 22 additions & 0 deletions charms/worker/k8s/src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

import charms.contextual_status as status
import charms.operator_libs_linux.v2.snap as snap_lib
import containerd
import ops
import reschedule
import yaml
Expand Down Expand Up @@ -297,6 +298,26 @@ def _bootstrap_k8s_snap(self):
# TODO: Make port (and address) configurable.
self.api_manager.bootstrap_k8s_snap(payload)

@on_error(
ops.BlockedStatus("Failed to apply containerd_custom_registries, check logs for details"),
ValueError,
subprocess.CalledProcessError,
OSError,
)
def _config_containerd_registries(self):
"""Apply containerd custom registries."""
registries, config = [], ""
containerd_relation = self.model.get_relation("containerd")
if self.is_control_plane:
config = self.config["containerd_custom_registries"]
registries = containerd.parse_registries(config)
else:
registries = containerd.recover(containerd_relation)
self.unit.status = ops.MaintenanceStatus("Ensuring containerd registries")
containerd.ensure_registry_configs(registries)
if self.lead_control_plane:
containerd.share(config, self.app, containerd_relation)

def _configure_cos_integration(self):
"""Retrieve the join token from secret databag and join the cluster."""
if not self.model.get_relation("cos-agent"):
Expand Down Expand Up @@ -588,6 +609,7 @@ def _reconcile(self, event: ops.EventBase):
self._revoke_cluster_tokens(event)
self._ensure_cluster_config()
self._join_cluster()
self._config_containerd_registries()
self._configure_cos_integration()
self._update_status()
self._apply_node_labels()
Expand Down
Loading

0 comments on commit 54dc67e

Please sign in to comment.