Skip to content

Commit

Permalink
Merge pull request #2 from charmed-kubernetes/KU-439/gcp-cloud-integr…
Browse files Browse the repository at this point in the history
…ation

Test load-balancer administration
  • Loading branch information
kwmonroe authored Mar 7, 2024
2 parents 405e26b + 2a51f4b commit 4dd7a32
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 178 deletions.
7 changes: 4 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
backports.cached-property
ops>=1.3.0,<2.0.0
ops
lightkube>=0.10.1,<1.0.0
pyyaml
pydantic==1.*
ops.manifest>=1.1.0,<2.0.0
git+https://github.com/charmed-kubernetes/interface-kube-control.git@6dd289d1c795fdeda1bed17873b8d6562227c829#subdirectory=ops
git+https://github.com/charmed-kubernetes/interface-tls-certificates.git@339efe3823b9728d16cdf5bcd1fc3b5de4e68923#subdirectory=ops
ops.interface-kube-control @ git+https://github.com/charmed-kubernetes/interface-kube-control.git@main#subdirectory=ops
ops.interface-tls-certificates @ git+https://github.com/charmed-kubernetes/interface-tls-certificates.git@main#subdirectory=ops
ops.interface_gcp @ git+https://github.com/charmed-kubernetes/interface-gcp-integration@main#subdirectory=ops
6 changes: 4 additions & 2 deletions src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from ops.charm import CharmBase
from ops.framework import StoredState
from ops.interface_gcp.requires import GCPIntegrationRequires
from ops.interface_kube_control import KubeControlRequirer
from ops.interface_tls_certificates import CertificatesRequires
from ops.main import main
Expand All @@ -16,7 +17,6 @@

from config import CharmConfig
from provider_manifests import GCPProviderManifests
from requires_gcp_integration import GCPIntegratorRequires

log = logging.getLogger(__name__)

Expand All @@ -32,7 +32,7 @@ def __init__(self, *args):
super().__init__(*args)

# Relation Validator and datastore
self.integrator = GCPIntegratorRequires(self)
self.integrator = GCPIntegrationRequires(self, "gcp-integration")
self.kube_control = KubeControlRequirer(self)
self.certificates = CertificatesRequires(self)
# Config Validator and datastore
Expand Down Expand Up @@ -105,6 +105,8 @@ def _sync_resources(self, event):

def _request_gcp_features(self, event):
self.integrator.enable_instance_inspection()
self.integrator.enable_network_management()
self.integrator.enable_security_management()
self._merge_config(event=event)

def _update_status(self, _):
Expand Down
12 changes: 8 additions & 4 deletions src/provider_manifests.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Copyright 2022 Canonical Ltd.
# See LICENSE file for licensing details.
"""Implementation of gcp specific details of the kubernetes manifests."""
import base64
import logging
import pickle
from hashlib import md5
Expand Down Expand Up @@ -31,11 +32,14 @@ class CreateSecret(Addition):

def __call__(self) -> Optional[AnyResource]:
"""Craft the secrets object for the deployment."""
secret_config = {SECRET_DATA: self.manifests.config.get(SECRET_DATA)}
if any(s is None for s in secret_config.values()):
log.error("secret data item is None")
creds: Optional[str] = self.manifests.config.get(SECRET_DATA)
if not creds:
log.error("secret data item is Unavailable")
return None

b64_creds = base64.b64encode(creds.encode()).decode()
secret_config = {SECRET_DATA: b64_creds}

log.info("Encoding secret data for cloud-controller.")
return from_dict(
dict(
Expand Down Expand Up @@ -179,7 +183,7 @@ def config(self) -> Dict:
"""Returns current config available from charm config and joined relations."""
config = {}
if self.integrator.is_ready:
config[SECRET_DATA] = self.integrator.credentials.decode()
config[SECRET_DATA] = self.integrator.credentials
if self.kube_control.is_ready:
config["image-registry"] = self.kube_control.get_registry_location()
config["control-node-taints"] = self.kube_control.get_controller_taints() or [
Expand Down
161 changes: 0 additions & 161 deletions src/requires_gcp_integration.py

This file was deleted.

4 changes: 3 additions & 1 deletion tests/data/charm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ description: Overlay for attaching current charm
applications:
gcp-integrator:
charm: gcp-integrator
channel: edge
channel: latest/stable
num_units: 1
trust: true
gcp-cloud-provider:
charm: {{charm}}
options:
enable-loadbalancers: true
relations:
- ["gcp-cloud-provider:certificates", "easyrsa:client"]
- ["gcp-cloud-provider:kube-control", "kubernetes-control-plane"]
Expand Down
42 changes: 42 additions & 0 deletions tests/data/lb-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: hello-world
run: load-balancer-example
name: hello
spec:
replicas: 5
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world
run: load-balancer-example
spec:
containers:
- image: rocks.canonical.com/cdk/google-samples/node-hello:1.0
name: node-hello
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: hello-world
run: load-balancer-example
name: hello
spec:
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
app: hello-world
type: LoadBalancer
status:
loadBalancer: {}
26 changes: 25 additions & 1 deletion tests/integration/test_gcp_cloud_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
# See LICENSE file for licensing details.
import logging
import shlex
import urllib.request
from pathlib import Path

import pytest
from lightkube.resources.core_v1 import Node
from lightkube.codecs import load_all_yaml
from lightkube.resources.apps_v1 import Deployment
from lightkube.resources.core_v1 import Node, Service

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -43,3 +46,24 @@ async def test_build_and_deploy(ops_test):
async def test_provider_ids(kubernetes):
async for node in kubernetes.list(Node):
assert node.spec.providerID.startswith("gce://")


async def test_loadbalancer(kubernetes):
log.info("Starting hello-world on port=8080.")
lb_yaml = Path("tests/data/lb-test.yaml")
lb_content = load_all_yaml(lb_yaml.open())
try:
for obj in lb_content:
await kubernetes.create(obj, obj.metadata.name)
await kubernetes.wait(Deployment, "hello", for_conditions=["Available"])
async for _, dep in kubernetes.watch(Service, fields={"metadata.name": "hello"}):
if dep.status.loadBalancer.ingress:
break
assert dep.status.loadBalancer.ingress[0].ip
with urllib.request.urlopen(
f"http://{dep.status.loadBalancer.ingress[0].ip}:8080"
) as resp:
assert b"Hello Kubernetes!" in resp.read()
finally:
for obj in lb_content:
await kubernetes.delete(type(obj), obj.metadata.name)
13 changes: 7 additions & 6 deletions tests/unit/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ def kube_control():
yield kube_control


@pytest.fixture()
@pytest.fixture(autouse=True)
def gcp_integration():
with mock.patch("charm.GCPIntegratorRequires") as mocked:
with mock.patch("charm.GCPIntegrationRequires") as mocked:
integration = mocked.return_value
integration.credentials = b"{}"
integration.evaluate_relation.return_value = None
integration.credentials = "{}"
integration.is_ready = False
yield integration


Expand Down Expand Up @@ -129,8 +129,9 @@ def test_waits_for_kube_control(mock_create_kubeconfig, harness):
assert charm.unit.status.message == "Provider manifests waiting for definition of gcp-creds"


@pytest.mark.usefixtures("certificates", "kube_control", "gcp_integration")
def test_waits_for_config(harness: Harness, lk_client, caplog):
@pytest.mark.usefixtures("certificates", "kube_control")
def test_waits_for_config(harness: Harness, lk_client, caplog, gcp_integration):
gcp_integration.is_ready = True
harness.begin_with_initial_hooks()
with mock.patch.object(lk_client, "list") as mock_list:
mock_list.return_value = [mock.Mock(**{"metadata.annotations": {}})]
Expand Down

0 comments on commit 4dd7a32

Please sign in to comment.