/slide02.sh Secret
Last active
March 2, 2023 07:36
Star
You must be signed in to star a gist
Operator Day 2021 - Demo Slide Gists
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Install/Setup MicroK8s | |
sudo snap install --classic microk8s | |
sudo usermod -aG microk8s $(whoami) | |
sudo microk8s status --wait-ready | |
sudo microk8s enable storage dns ingress | |
sudo snap alias microk8s.kubectl kubectl | |
newgrp microk8s | |
# Install Charmcraft | |
sudo snap install lxd --classic | |
sudo lxd init --auto | |
sudo snap install charmcraft --classic | |
# Install Juju | |
sudo snap install juju --classic | |
# Bootstrap MicroK8s | |
juju bootstrap microk8s micro | |
juju add-model development |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Install/Setup MicroK8s | |
sudo snap install --classic microk8s | |
sudo usermod -aG microk8s $(whoami) | |
sudo microk8s status --wait-ready | |
sudo microk8s enable storage dns ingress | |
sudo snap alias microk8s.kubectl kubectl | |
newgrp microk8s | |
# Install Charmcraft | |
sudo snap install lxd --classic | |
sudo lxd init --auto | |
sudo snap install charmcraft --classic | |
# Install Juju | |
sudo snap install juju --classic | |
# Bootstrap MicroK8s | |
juju bootstrap microk8s micro | |
juju add-model development |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Create the Charm directory | |
mkdir hello-kubecon; cd hello-kubecon | |
# Initialise the Charm directory | |
charmcraft init |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Ensure that virtualenv support is installed | |
sudo apt update && sudo apt install -y python3-virtualenv | |
# Create a virtualenv for the charm code | |
virtualenv venv | |
# Activate the venv | |
source ./venv/bin/activate | |
# Install dependencies | |
pip install -r requirements-dev.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright 2021 Jon Seager | |
# See LICENSE file for licensing details. | |
name: hello-kubecon | |
description: | | |
A basic demonstration charm that hosts a placeholder webpage with links | |
to various Juju/Charmed Operator SDK pages. Hosted using a small, custom | |
webserver written in Go (https://github.com/jnsgruk/gosherve). Illustrates | |
the use of charm workloads, actions, config, storage and relations. | |
summary: | | |
A demonstration charm for Kubecon Operator Day 2021. | |
containers: | |
gosherve: | |
resource: gosherve-image | |
resources: | |
gosherve-image: | |
type: oci-image | |
description: OCI image for gosherve |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def _on_gosherve_pebble_ready(self, event): | |
"""Define and start a workload using the Pebble API""" | |
# Get a reference the container attribute on the PebbleReadyEvent | |
container = event.workload | |
# Define an initial Pebble layer configuration | |
pebble_layer = { | |
"summary": "gosherve layer", | |
"description": "pebble config layer for gosherve", | |
"services": { | |
"gosherve": { | |
"override": "replace", | |
"summary": "gosherve", | |
"command": "/gosherve", | |
"startup": "enabled", | |
"environment": { | |
"REDIRECT_MAP_URL": "https://jnsgr.uk/demo-routes" | |
}, | |
} | |
}, | |
} | |
# Add intial Pebble config layer using the Pebble API | |
container.add_layer("gosherve", pebble_layer, combine=True) | |
# Autostart any services that were defined with startup: enabled | |
container.autostart() | |
# Learn more about statuses in the SDK docs: | |
# https://juju.is/docs/sdk/constructs#heading--statuses | |
self.unit.status = ActiveStatus() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Build the charm | |
charmcraft pack | |
# Deploy the charm | |
juju deploy ./hello-kubecon.charm --resource gosherve-image=jnsgruk/gosherve | |
# Check the Juju status | |
watch -n1 --color juju status --color |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Set the log level to DEBUG for the development model | |
juju model-config logging-config="<root>=WARNING;unit=DEBUG" | |
# Follow the debug-log | |
juju debug-log | |
# Explore with kubectl | |
kubectl -n development get pods |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright 2021 Jon Seager | |
# See LICENSE file for licensing details. | |
# | |
# Learn more about config at: https://juju.is/docs/sdk/config | |
options: | |
redirect-map: | |
default: "https://jnsgr.uk/demo-routes" | |
description: A URL pointing to a list of redirects for Gosherve. | |
type: string |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def _gosherve_layer(self): | |
"""Returns a Pebble configration layer for Gosherve""" | |
return { | |
"summary": "gosherve layer", | |
"description": "pebble config layer for gosherve", | |
"services": { | |
"gosherve": { | |
"override": "replace", | |
"summary": "gosherve", | |
"command": "/gosherve", | |
"startup": "enabled", | |
"environment": { | |
"REDIRECT_MAP_URL": self.config["redirect-map"] | |
}, | |
} | |
}, | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def _on_config_changed(self, event): | |
"""Handle the config-changed event""" | |
# Get the gosherve container so we can configure/manipulate it | |
container = self.unit.get_container("gosherve") | |
# Create a new config layer | |
layer = self._gosherve_layer() | |
# Get the current config | |
services = container.get_plan().to_dict().get("services", {}) | |
# Check if there are any changes to services | |
if services != layer["services"]: | |
# Changes were made, add the new layer | |
container.add_layer("gosherve", layer, combine=True) | |
logging.info("Added updated layer 'gosherve' to Pebble plan") | |
# Stop the service if it is already running | |
if container.get_service("gosherve").is_running(): | |
container.stop("gosherve") | |
# Restart it and report a new status to Juju | |
container.start("gosherve") | |
logging.info("Restarted gosherve service") | |
# All is well, set an ActiveStatus | |
self.unit.status = ActiveStatus() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Build the charm | |
charmcraft pack | |
# Deploy the charm | |
juju refresh hello-kubecon --path=./hello-kubecon.charm | |
# Check the juju status - note the blocked status | |
watch -n1 --color juju status --color | |
# Change the configuration | |
juju config hello-kubecon redirect-map="https://jnsgr.uk/demo-routes-alt" | |
# Check the juju status - note the active status | |
watch -n1 --color juju status --color |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def _gosherve_layer(self): | |
"""Returns a Pebble configration layer for Gosherve""" | |
return { | |
"summary": "gosherve layer", | |
"description": "pebble config layer for gosherve", | |
"services": { | |
"gosherve": { | |
"override": "replace", | |
"summary": "gosherve", | |
"command": "/gosherve", | |
"startup": "enabled", | |
"environment": { | |
"REDIRECT_MAP_URL": self.config["redirect-map"], | |
"WEBROOT": "/srv", | |
}, | |
} | |
}, | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright 2021 Jon Seager | |
# See LICENSE file for licensing details. | |
name: hello-kubecon | |
description: | | |
A basic demonstration charm that hosts a placeholder webpage with links | |
to various Juju/Charmed Operator SDK pages. Hosted using a small, custom | |
webserve written in Go (https://github.com/jnsgruk/gosherve). Illustrates | |
the use of charm workloads, actions, config, storage and relations. | |
summary: | | |
A demonstration charm for Kubecon Operator Day 2021. | |
containers: | |
gosherve: | |
resource: gosherve-image | |
mounts: | |
- storage: webroot | |
location: /srv | |
resources: | |
gosherve-image: | |
type: oci-image | |
description: OCI image for gosherve | |
storage: | |
webroot: | |
type: filesystem | |
location: /srv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def _gosherve_layer(self): | |
"""Returns a Pebble configration layer for Gosherve""" | |
return { | |
"summary": "gosherve layer", | |
"description": "pebble config layer for gosherve", | |
"services": { | |
"gosherve": { | |
"override": "replace", | |
"summary": "gosherve", | |
"command": "/gosherve", | |
"startup": "enabled", | |
"environment": { | |
"REDIRECT_MAP_URL": self.config["redirect-map"], | |
"WEBROOT": "/srv", | |
}, | |
} | |
}, | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class HelloKubeconCharm(CharmBase): | |
"""Charm the service.""" | |
def __init__(self, *args): | |
super().__init__(*args) | |
self.framework.observe(self.on.install, self._on_install) | |
self.framework.observe(self.on.config_changed, self._on_config_changed) | |
def _on_install(self, _): | |
# Download the site | |
self._fetch_site() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def _fetch_site(self): | |
"""Fetch latest copy of website from Github and move into webroot""" | |
# Set the site URL | |
site_src = "https://jnsgr.uk/demo-site" | |
# Set some status and do some logging | |
self.unit.status = MaintenanceStatus("Fetching web site") | |
logger.info("Downloading site from %s", site_src) | |
# Download the site | |
urllib.request.urlretrieve(site_src, "/srv/index.html") | |
# Set the unit status back to Active | |
self.unit.status = ActiveStatus() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Build the charm | |
charmcraft pack | |
# Remove old charm (cannot refresh -- storage) | |
juju remove-application hello-kubecon | |
# Redeploy | |
juju deploy ./hello-kubecon.charm --resource gosherve-image=jnsgruk/gosherve | |
# Check the juju status | |
watch -n1 --color juju status --color | |
# Verify | |
$ curl "http://$(juju show-unit hello-kubecon/0 | grep -Po 'address: \K.+'):8080/" | |
# Explore | |
kubectl -n development describe pod hello-kubecon-0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright 2021 Jon Seager | |
# See LICENSE file for licensing details. | |
# | |
# Learn more about actions at: https://juju.is/docs/sdk/actions | |
pull-site: | |
description: Unpack latest version of website from remote source. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ... | |
def __init__(self, *args): | |
super().__init__(*args) | |
self.framework.observe(self.on.install, self._on_install) | |
self.framework.observe(self.on.config_changed, self._on_config_changed) | |
self.framework.observe(self.on.pull_site_action, self._pull_site_action) | |
# ... | |
def _pull_site_action(self, event): | |
"""Action handler that pulls the latest site archive and unpacks it""" | |
self._fetch_site() | |
event.set_results({"result": "site pulled"}) | |
# ... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Build the charm | |
charmcraft pack | |
# Refresh the deployment | |
juju refresh hello-kubecon --path=./hello-kubecon.charm | |
# Check the juju status | |
watch -n1 --color juju status --color | |
# Opt-in to new actions UX | |
export JUJU_FEATURES=actions-v2 | |
# Run the action | |
juju run hello-kubecon/0 pull-site | |
juju run hello-kubecon/0 pull-site --format=yaml | |
juju run hello-kubecon/0 pull-site --background | |
# Check the debug-log | |
juju debug-log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Check the there is a library associated with the charm | |
charmcraft list-lib nginx-ingress-integrator | |
# Fetch the library into our charm | |
charmcraft fetch-lib charms.nginx_ingress_integrator.v0.ingress | |
# Ensure library was imported into the correct place | |
ls -l lib/charms/nginx_ingress_integrator/v0/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: hello-kubecon | |
description: | | |
A basic demonstration charm that hosts a placeholder webpage with links | |
to various Juju/Charmed Operator SDK pages. Hosted using a small, custom | |
webserver written in Go (https://github.com/jnsgruk/gosherve). Illustrates | |
the use of charm workloads, actions, config, storage and relations. | |
summary: | | |
A demonstration charm for Kubecon Operator Day 2021. | |
# ... | |
requires: | |
ingress: | |
interface: ingress |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from charms.nginx_ingress_integrator.v0.ingress import IngressRequires | |
#... | |
class HelloKubeconCharm(CharmBase): | |
"""Charm the service.""" | |
def __init__(self, *args): | |
super().__init__(*args) | |
self.framework.observe(self.on.install, self._on_install) | |
self.framework.observe(self.on.config_changed, self._on_config_changed) | |
self.framework.observe(self.on.pull_site_action, self._pull_site_action) | |
self.ingress = IngressRequires(self, { | |
"service-hostname": "hellokubecon.juju", | |
"service-name": self.app.name, | |
"service-port": 8080 | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Build the charm | |
charmcraft pack | |
# Refresh the deployment | |
juju refresh hello-kubecon --path=./hello-kubecon.charm | |
# Deploy the nginx-ingress-integrator | |
juju deploy nginx-ingress-integrator | |
# Relate our application to the ingress integrator | |
juju relate hello-kubecon nginx-ingress-integrator | |
# Set the ingress class for microk8s | |
juju config nginx-ingress-integrator ingress-class="public" | |
# Add an entry to our hosts file | |
echo "127.0.1.1 hellokubecon.juju" | sudo tee -a /etc/hosts | |
# Check the juju status | |
watch -n1 --color juju status --color | |
# Verify | |
curl hellokubecon.juju |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def test_gosherve_layer(self): | |
# Test with empty config. | |
self.assertEqual(self.harness.charm.config['redirect-map'], "https://jnsgr.uk/demo-routes") | |
expected = { | |
"summary": "gosherve layer", | |
"description": "pebble config layer for gosherve", | |
"services": { | |
"gosherve": { | |
"override": "replace", | |
"summary": "gosherve", | |
"command": "/gosherve", | |
"startup": "enabled", | |
"environment": { | |
"REDIRECT_MAP_URL": "https://jnsgr.uk/demo-routes", | |
"WEBROOT": "/srv", | |
}, | |
} | |
}, | |
} | |
self.assertEqual(self.harness.charm._gosherve_layer(), expected) | |
# And now test with a different value in the redirect-map config option. | |
# Disable hook firing first. | |
self.harness.disable_hooks() | |
self.harness.update_config({"redirect-map": "test value"}) | |
expected["services"]["gosherve"]["environment"]["REDIRECT_MAP_URL"] = "test value" | |
self.assertEqual(self.harness.charm._gosherve_layer(), expected) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def test_on_config_changed(self): | |
plan = self.harness.get_container_pebble_plan("gosherve") | |
self.assertEqual(plan.to_dict(), {}) | |
# Trigger a config-changed hook. Since there was no plan initially, the | |
# "gosherve" service in the container won't be running so we'll be | |
# testing the `is_running() == False` codepath. | |
self.harness.update_config({"redirect-map": "test value"}) | |
plan = self.harness.get_container_pebble_plan("gosherve") | |
# Get the expected layer from the gosherve_layer method (tested above) | |
expected = self.harness.charm._gosherve_layer() | |
expected.pop("summary", "") | |
expected.pop("description", "") | |
# Check the plan is as expected | |
self.assertEqual(plan.to_dict(), expected) | |
self.assertEqual(self.harness.model.unit.status, ActiveStatus()) | |
container = self.harness.model.unit.get_container("gosherve") | |
self.assertEqual(container.get_service("gosherve").is_running(), True) | |
# Now test again with different config, knowing that the "gosherve" | |
# service is running (because we've just tested it above), so we'll | |
# be testing the `is_running() == True` codepath. | |
self.harness.update_config({"redirect-map": "test2 value"}) | |
plan = self.harness.get_container_pebble_plan("gosherve") | |
# Adjust the expected plan | |
expected["services"]["gosherve"]["environment"]["REDIRECT_MAP_URL"] = "test2 value" | |
self.assertEqual(plan.to_dict(), expected) | |
self.assertEqual(container.get_service("gosherve").is_running(), True) | |
self.assertEqual(self.harness.model.unit.status, ActiveStatus()) | |
# And finally test again with the same config to ensure we exercise | |
# the case where the plan we've created matches the active one. We're | |
# going to mock the container.stop and container.start calls to confirm | |
# they were not called. | |
with patch('ops.model.Container.start') as _start, patch('ops.model.Container.stop') as _stop: | |
self.harness.charm.on.config_changed.emit() | |
_start.assert_not_called() | |
_stop.assert_not_called() |
@kapkic Updated, thanks!
In https://gist.github.com/jnsgruk/53313fa93475ff13a396e292100a3024#file-slide58-sh the first comment is not clear, it says:
# Check the there is a library associated with the charm
I think the intent is to say "Check that
there is...", which is one thing, however I had trouble figuring out which charm
is meant here - is it the charm being developed here or the ingress one? I figured it out, but perhaps if being explicit it will be better.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
When installing charmcraft by
sudo snap install charmcraft
, snap returns an error: This revision of snap "charmcraft" was published using classic confinement...Adding --classic at the end resolves it. I have updated it on my local fork, which should run without an error.
https://gist.github.com/kapkic/8cd2e838969dc185657da5baacf17e57/revisions
Can you update/pull it if possible?
Thanks for the gist!