Skip to content

Commit

Permalink
Upgrade tests to juju 3.1 (#211)
Browse files Browse the repository at this point in the history
* Upgrade tests to juju 3.1

* Update test_etcd.py

use model destroy_unit()

* Stop listening on 127.0.0.1:4001 with http (#212)

* Stop listening on 127.0.0.1:4001 with http

* Ensure the restore action uses the secure endpoint as well

* linting

* Update config.yaml

Co-authored-by: Kevin W Monroe <[email protected]>

---------

Co-authored-by: Kevin W Monroe <[email protected]>

---------

Co-authored-by: Kevin W Monroe <[email protected]>
  • Loading branch information
addyess and kwmonroe authored Sep 22, 2023
1 parent b688b58 commit bbb2ed3
Show file tree
Hide file tree
Showing 13 changed files with 119 additions and 123 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/vsphere-integration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ jobs:
uses: charmed-kubernetes/actions-operator@main
with:
provider: vsphere
juju-channel: 3.1/stable
credentials-yaml: ${{ secrets.CREDENTIALS_YAML }}
clouds-yaml: ${{ secrets.CLOUDS_YAML }}
bootstrap-constraints: "arch=amd64 cores=2 mem=4G"
bootstrap-options: "${{ secrets.FOCAL_BOOTSTRAP_OPTIONS }} --model-default datastore=vsanDatastore --model-default primary-network=VLAN_2763"
bootstrap-options: "${{ secrets.JAMMY_BOOTSTRAP_OPTIONS }} --model-default datastore=vsanDatastore --model-default primary-network=VLAN_2763"
- name: Run test
run: tox -e integration
run: tox -e integration -- --basetemp=/home/ubuntu/pytest
- name: Setup Debug Artifact Collection
if: ${{ failure() }}
run: mkdir tmp
Expand Down
8 changes: 4 additions & 4 deletions actions/restore.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from charms import layer
from charmhelpers.core.templating import render
from charmhelpers.core import hookenv
from charmhelpers.core.hookenv import function_fail
from charmhelpers.core.hookenv import action_fail
from charmhelpers.core.hookenv import action_get
from charmhelpers.core.hookenv import action_set
from charmhelpers.core.hookenv import config
Expand Down Expand Up @@ -56,10 +56,10 @@
def preflight_check():
"""Check preconditions for data restoration"""
if not is_leader():
function_fail("This action can only be run on the leader unit")
action_fail("This action can only be run on the leader unit")
sys.exit(0)
if not SNAPSHOT_ARCHIVE:
function_fail({"result.failed": "Missing snapshot. See: README.md"})
action_fail("Missing snapshot. See: README.md")
sys.exit(0)


Expand Down Expand Up @@ -112,7 +112,7 @@ def restore_v3_backup():
# Use the insecure 4001 port we have open in our deployment
environ = dict(os.environ, ETCDCTL_API="3")
cmd = (
"/snap/bin/etcdctl --endpoints=http://localhost:4001 snapshot "
"/snap/bin/etcdctl --endpoints=https://127.0.0.1:2379 snapshot "
"restore /root/tmp/restore-v3/db --skip-hash-check "
"--data-dir='/root/tmp/restore-v3/etcd' "
"--initial-cluster='{}' --initial-cluster-token='{}' "
Expand Down
6 changes: 6 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ options:
description: |
The service binds to all network interfaces if true. The service binds
only to the first found bind address of each relation if false
bind_with_insecure_http:
type: boolean
default: false
description: |
The service binds to localhost:4001 with http if true. This exposes an insecure
endpoint for the service and is not recommended in production environments.
tls_cipher_suites:
type: string
default: ""
Expand Down
8 changes: 6 additions & 2 deletions lib/etcd_databag.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,16 @@ def __init__(self):
self.db = unitdata.kv()
self.build_uri = build_uri
self.cluster_bind_address = self.get_bind_address("cluster")
self.db_bind_address = self.get_bind_address("db")
self.port = config("port")
self.listen_client_urls = [
build_uri("https", self.get_bind_address("db"), self.port)
]
if config("bind_with_insecure_http"):
self.listen_client_urls.insert(0, build_uri("http", "127.0.0.1", 4001))
self.advertise_urls = [build_uri("https", get_ingress_address("db"), self.port)]
self.management_port = config("management_port")
# Live polled properties
self.cluster_address = get_ingress_address("cluster")
self.db_address = get_ingress_address("db")
self.unit_name = os.getenv("JUJU_UNIT_NAME").replace("/", "")

# Pull the TLS certificate paths from layer data
Expand Down
26 changes: 12 additions & 14 deletions lib/etcdctl.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from subprocess import CalledProcessError
from subprocess import check_output
from subprocess import STDOUT
from typing import Optional
import os
from etcd_lib import build_uri

Expand Down Expand Up @@ -66,7 +67,7 @@ def unregister(self, unit_id, leader_address=None):
"""
return self.run(["member", "remove", unit_id], endpoints=leader_address, api=2)

def member_list(self, leader_address=False):
def member_list(self, leader_address=None):
"""Returns the output from `etcdctl member list` as a python dict
organized by unit_name, containing all the data-points in the resulting
response."""
Expand Down Expand Up @@ -122,7 +123,7 @@ def cluster_health(self, output_only=False):
organized by topical information with detailed unit output"""
health = {}
try:
out = self.run("cluster-health", endpoints=False, api=2)
out = self.run("cluster-health", endpoints=None, api=2)
if output_only:
return out
health_output = out.strip("\n").split("\n")
Expand All @@ -134,7 +135,7 @@ def cluster_health(self, output_only=False):
health["units"] = []
return health

def run(self, arguments, endpoints=None, api=3):
def run(self, arguments, endpoints: Optional[str] = None, api=3):
"""Wrapper to subprocess calling output. This is a convenience
method to clean up the calls to subprocess and append TLS data"""
env = {}
Expand All @@ -149,20 +150,18 @@ def run(self, arguments, endpoints=None, api=3):
env["ETCDCTL_CACERT"] = ca_path
env["ETCDCTL_CERT"] = crt_path
env["ETCDCTL_KEY"] = key_path
if endpoints is None:
endpoints = "http://127.0.0.1:4001"

elif api == 2:
env["ETCDCTL_API"] = "2"
env["ETCDCTL_CA_FILE"] = ca_path
env["ETCDCTL_CERT_FILE"] = crt_path
env["ETCDCTL_KEY_FILE"] = key_path
if endpoints is None:
endpoints = ":4001"

else:
raise NotImplementedError("etcd api version {} not supported".format(api))

if not endpoints:
endpoints = "https://127.0.0.1:2379"

if isinstance(arguments, str):
command.extend(arguments.split())
elif isinstance(arguments, list) or isinstance(arguments, tuple):
Expand All @@ -172,12 +171,11 @@ def run(self, arguments, endpoints=None, api=3):
"arguments not correct type; must be string, list or tuple"
)

if endpoints is not False:
if api == 3:
command.extend(["--endpoints", endpoints])
elif api == 2:
command.insert(1, "--endpoint")
command.insert(2, endpoints)
if api == 3:
command.extend(["--endpoints", endpoints])
elif api == 2:
command.insert(1, "--endpoint")
command.insert(2, endpoints)

try:
return check_output(command, env=env, stderr=STDOUT).decode("utf-8")
Expand Down
2 changes: 1 addition & 1 deletion templates/check_etcd-alarms.cron
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# check_etcd_alarms
* * * * * root [ -x /snap/bin/etcdctl ] && ETCDCTL_API=3 /snap/bin/etcdctl --endpoints=127.0.0.1:4001 alarm list 2>&1| tee /var/lib/nagios/etcd-alarm-list.txt > /dev/null
* * * * * root [ -x /snap/bin/etcdctl ] && ETCDCTL_API=3 ETCDCTL_KEY=/var/snap/etcd/common/client.key ETCDCTL_CERT=/var/snap/etcd/common/client.crt ETCDCTL_CACERT=/var/snap/etcd/common/ca.crt /snap/bin/etcdctl --endpoints=https://127.0.0.1:2379 alarm list 2>&1| tee /var/lib/nagios/etcd-alarm-list.txt > /dev/null
4 changes: 2 additions & 2 deletions templates/etcd2.conf
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# This file is rendered by Juju, manual edits will not be persisted
ETCD_DATA_DIR={{ etcd_data_dir }}/{{ unit_name }}.etcd
ETCD_NAME={{ unit_name }}
ETCD_ADVERTISE_CLIENT_URLS="{{ build_uri('https', db_address, port) }}"
ETCD_LISTEN_CLIENT_URLS="http://127.0.0.1:4001,{{ build_uri('https', db_bind_address, port) }}"
ETCD_ADVERTISE_CLIENT_URLS="{{ advertise_urls | join(',') }}"
ETCD_LISTEN_CLIENT_URLS="{{ listen_client_urls | join(',') }}"
ETCD_LISTEN_PEER_URLS="{{ build_uri('https', cluster_bind_address, management_port) }}"
ETCD_INITIAL_ADVERTISE_PEER_URLS="{{ build_uri('https', cluster_address, management_port) }}"
{% if cluster %}
Expand Down
4 changes: 2 additions & 2 deletions templates/etcd3.conf
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ quota-backend-bytes: 0

listen-peer-urls: {{ build_uri('https', cluster_bind_address, management_port) }}
# List of comma separated URLs to listen on for client traffic.
listen-client-urls: http://127.0.0.1:4001,{{ build_uri('https', db_bind_address, port) }}
listen-client-urls: {{ listen_client_urls | join(",") }}

# Maximum number of snapshot files to retain (0 is unlimited).
max-snapshots: 5
Expand All @@ -49,7 +49,7 @@ initial-advertise-peer-urls: {{ build_uri('https', cluster_address, management_p

# List of this member's client URLs to advertise to the public.
# The URLs needed to be a comma-separated list.
advertise-client-urls: {{ build_uri('https', db_address, port) }}
advertise-client-urls: {{ advertise_urls | join(",") }}

# Discovery URL used to bootstrap the cluster.
discovery:
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ def pytest_addoption(parser):
parser.addoption(
"--series",
type=str,
default="focal",
default="jammy",
help="Set series for the machine units",
)

Expand Down
Loading

0 comments on commit bbb2ed3

Please sign in to comment.