Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create hockeypuck rock and update charm files #3

Merged
merged 18 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .licenserc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@ header:
- '.github/**'
- '**/*.json'
- '**/*.md'
- '**/*.conf'
- '**/*.conf.tmpl'
- '**/*.txt'
- '.jujuignore'
- '.gitignore'
- '.licenserc.yaml'
- '.trivyignore'
- '.woke.yaml'
- '.woke.yml'
- 'CODEOWNERS'
- 'LICENSE'
- 'trivy.yaml'
Expand Down
3 changes: 3 additions & 0 deletions .trivyignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
GHSA-9763-4f94-gfch

Check notice on line 1 in .trivyignore

View workflow job for this annotation

GitHub Actions / integration-tests / Scan Image (ghcr.io-canonical-hockeypuck-1d4ea10e9cb3fa9cd3037f7b36cd3885a983b3b6-_0.1_amd64.tar)

GHSA-9763-4f94-gfch not present anymore, can be safely removed.
CVE-2024-45337

Check notice on line 2 in .trivyignore

View workflow job for this annotation

GitHub Actions / integration-tests / Scan Image (ghcr.io-canonical-hockeypuck-1d4ea10e9cb3fa9cd3037f7b36cd3885a983b3b6-_0.1_amd64.tar)

CVE-2024-45337 not present anymore, can be safely removed.
CVE-2024-45338

Check notice on line 3 in .trivyignore

View workflow job for this annotation

GitHub Actions / integration-tests / Scan Image (ghcr.io-canonical-hockeypuck-1d4ea10e9cb3fa9cd3037f7b36cd3885a983b3b6-_0.1_amd64.tar)

CVE-2024-45338 not present anymore, can be safely removed.
3 changes: 3 additions & 0 deletions .woke.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
rules:
swetha1654 marked this conversation as resolved.
Show resolved Hide resolved
# Ignore "blacklist" - since the hockeypuck binaries look for this configuation option
- name: blacklist
55 changes: 46 additions & 9 deletions charmcraft.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,50 @@
# Copyright 2025 Canonical Ltd.
# See LICENSE file for licensing details.
# This file configures Charmcraft.
# See https://juju.is/docs/sdk/charmcraft-config for guidance.

type: charm
bases:
- build-on:
- name: ubuntu
channel: "22.04"
run-on:
- name: ubuntu
channel: "22.04"
name: hockeypuck-k8s
title: Hockeypuck K8S Charm
summary: Hockeypuck OpenPGP public keyserver
links:
documentation: https://discourse.charmhub.io/t/hockeypuck-documentation-overview/16591
issues: https://github.com/canonical/hockeypuck-k8s-operator/issues
source: https://github.com/canonical/hockeypuck-k8s-operator
contact: https://launchpad.net/~canonical-is-devops

description: |
A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators)
for deploying and managing [Hockeypuck](https://hockeypuck.io/) on Kubernetes. Hockeypuck is an
OpenPGP public keyserver tool used to manage public key infrastructure for PGP
(Pretty Good Privacy). PGP is a system for securing communication through encryption and
digital signatures.

The server provides interfaces to add, look up, replace and delete public keys from the
keyserver. Hockeypuck can synchronize public key material with SKS (Synchronizing Key Server)
and other Hockeypuck servers. It implements the HTTP Keyserver Protocol and the SKS database
reconciliation protocol.

For DevOps and SRE teams, this charm will make operating Hockeypuck simple and straightforward
through Juju's clean interface.

assumes:
- juju >= 3.4
- k8s-api

containers:
hockeypuck:
resource: hockeypuck-image

resources:
hockeypuck-image:
type: oci-image
description: OCI image for Hockeypuck

requires:
database:
interface: postgresql_client
limit: 1

base: [email protected]
build-base: [email protected]
platforms:
amd64:
44 changes: 44 additions & 0 deletions hockeypuck_rock/hockeypuck.conf.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Initial config file for hockeypuck docker-compose/standalone deployments
# Environment variables are substituted using golang template markup
# See https://pkg.go.dev/text/template

[hockeypuck]
loglevel="INFO"
indexTemplate="/hockeypuck/lib/templates/index.html.tmpl"
vindexTemplate="/hockeypuck/lib/templates/index.html.tmpl"
statsTemplate="/hockeypuck/lib/templates/stats.html.tmpl"
webroot="/hockeypuck/lib/www"
hostname="${FQDN}"
contact="${FINGERPRINT}"
adminKeys=[
# List your admin key fingerprint(s) here.
# It is NOT RECOMMENDED to use the same key for both contact and admin.
]

[hockeypuck.hkp]
bind=":11371"
logRequestDetails=false

# prevent abusively large keys
[hockeypuck.openpgp]
maxPacketLength=8192
maxKeyLength=1048576
# Full fingerprints of keys to ignore, minus the leading 0x
blacklist=[
swetha1654 marked this conversation as resolved.
Show resolved Hide resolved
# "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
]

[hockeypuck.openpgp.db]
driver="postgres-jsonb"
dsn="database=hockeypuck host=${POSTGRES_HOST} user=${POSTGRES_USER} password=${POSTGRES_PASSWORD} port=${POSTGRES_PORT} sslmode=disable"
swetha1654 marked this conversation as resolved.
Show resolved Hide resolved

[hockeypuck.conflux.recon]
allowCIDRs=["127.0.0.1/8"]

[hockeypuck.conflux.recon.leveldb]
path="/hockeypuck/data/ptree"

# Gossip peers
#[hockeypuck.conflux.recon.partner.keyserver_example_com]
#httpAddr="keyserver.example.com:11371"
#reconAddr="keyserver.example.com:11370"
18 changes: 18 additions & 0 deletions hockeypuck_rock/hockeypuck_wrapper.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash
swetha1654 marked this conversation as resolved.
Show resolved Hide resolved

# Copyright 2025 Canonical Ltd.
# See LICENSE file for licensing details.

TEMPLATE_FILE="/hockeypuck/etc/hockeypuck.conf.tmpl"
OUTPUT_FILE="/hockeypuck/etc/hockeypuck.conf"

if [[ ! -f $TEMPLATE_FILE ]]; then
echo "Template file $TEMPLATE_FILE not found." >&2
exit 1
fi

envsubst < "$TEMP_FILE" > "$OUTPUT_FILE"

echo "Substitution complete. Output written to $OUTPUT_FILE."

exec /hockeypuck/bin/hockeypuck -config $OUTPUT_FILE
42 changes: 42 additions & 0 deletions hockeypuck_rock/rockcraft.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright 2025 Canonical Ltd.
# See LICENSE file for licensing details.

name: hockeypuck
base: [email protected]
version: 0.1
summary: Hockeypuck is an OpenPGP public keyserver.
description: |
Hockeypuck is an OpenPGP public keyserver tool used to manage public key
infrastructure for PGP (Pretty Good Privacy). PGP is a system for securing
communication through encryption and digital signatures.
platforms:
amd64:
build-on:
- amd64
build-for:
- amd64
parts:
hockeypuck:
plugin: make
source: https://github.com/hockeypuck/hockeypuck.git
source-tag: 2.2.2
source-type: git
source-depth: 1
build-snaps:
- go
organize:
usr/bin/hockeypuck: hockeypuck/bin/hockeypuck
usr/bin/hockeypuck-dump: hockeypuck/bin/hockeypuck-dump
usr/bin/hockeypuck-load: hockeypuck/bin/hockeypuck-load
usr/bin/hockeypuck-pbuild: hockeypuck/bin/hockeypuck-pbuild
var/lib/hockeypuck/*: hockeypuck/lib/
stage-packages:
- gettext-base
copy-files:
plugin: dump
source: .
organize:
hockeypuck.conf.tmpl: hockeypuck/etc/hockeypuck.conf.tmpl
hockeypuck_wrapper.sh: hockeypuck/bin/hockeypuck_wrapper.sh
prime:
- hockeypuck/*
50 changes: 0 additions & 50 deletions metadata.yaml

This file was deleted.

12 changes: 9 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
# Copyright 2025 Canonical Ltd.
# See LICENSE file for licensing details.

"""Fixtures for charm tests."""
"""Fixtures for hockeypuck-k8s tests."""

import pytest

def pytest_addoption(parser):

def pytest_addoption(parser: pytest.Parser):
"""Parse additional pytest options.
Args:
parser: Pytest parser.
"""
parser.addoption("--charm-file", action="store")
# The prebuilt charm file.
parser.addoption("--charm-file", action="store", default="")
# The Hockeypuck image name:tag.
parser.addoption("--hockeypuck-image", action="store", default="")
# The path to kubernetes config.
13 changes: 6 additions & 7 deletions tests/integration/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,24 @@

logger = logging.getLogger(__name__)

METADATA = yaml.safe_load(Path("./metadata.yaml").read_text(encoding="utf-8"))
APP_NAME = METADATA["name"]


@pytest.mark.abort_on_fail
@pytest.mark.skip(reason="Will enable again while raising PR for integration tests")
async def test_build_and_deploy(ops_test: OpsTest, pytestconfig: pytest.Config):
"""Deploy the charm together with related charms.

Assert on the unit status before any relations/configurations take place.
"""
# Deploy the charm and wait for active/idle status
metadata = yaml.safe_load(Path("./metadata.yaml").read_text(encoding="utf-8"))
app_name = metadata["name"]
charm = pytestconfig.getoption("--charm-file")
resources = {"httpbin-image": METADATA["resources"]["httpbin-image"]["upstream-source"]}
resources = {"httpbin-image": metadata["resources"]["httpbin-image"]["upstream-source"]}
assert ops_test.model
await asyncio.gather(
ops_test.model.deploy(
f"./{charm}", resources=resources, application_name=APP_NAME, series="jammy"
f"./{charm}", resources=resources, application_name=app_name, series="jammy"
),
ops_test.model.wait_for_idle(
apps=[APP_NAME], status="active", raise_on_blocked=True, timeout=1000
apps=[app_name], status="active", raise_on_blocked=True, timeout=1000
),
)
4 changes: 4 additions & 0 deletions tests/unit/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def setUp(self):
self.addCleanup(self.harness.cleanup)
self.harness.begin()

@unittest.skip("Skipping all tests until PR is raised for unit tests")
def test_httpbin_pebble_ready(self):
# Expected plan after Pebble ready with default config
expected_plan = {
Expand All @@ -48,6 +49,7 @@ def test_httpbin_pebble_ready(self):
# Ensure we set an ActiveStatus with no message
self.assertEqual(self.harness.model.unit.status, ops.ActiveStatus())

@unittest.skip("Skipping all tests until PR is raised for unit tests")
def test_config_changed_valid_can_connect(self):
# Ensure the simulated Pebble API is reachable
self.harness.set_can_connect("httpbin", True)
Expand All @@ -60,12 +62,14 @@ def test_config_changed_valid_can_connect(self):
self.assertEqual(updated_env, {"GUNICORN_CMD_ARGS": "--log-level debug"})
self.assertEqual(self.harness.model.unit.status, ops.ActiveStatus())

@unittest.skip("Skipping all tests until PR is raised for unit tests")
def test_config_changed_valid_cannot_connect(self):
# Trigger a config-changed event with an updated value
self.harness.update_config({"log-level": "debug"})
# Check the charm is in WaitingStatus
self.assertIsInstance(self.harness.model.unit.status, ops.WaitingStatus)

@unittest.skip("Skipping all tests until PR is raised for unit tests")
def test_config_changed_invalid(self):
# Ensure the simulated Pebble API is reachable
self.harness.set_can_connect("httpbin", True)
Expand Down
Loading