canonical / ops-scenario

State-transition testing SDK for Operator Framework Juju charms.
Apache License 2.0
10 stars 7 forks source link

UncaughtCharmError when container names contain dashes (-) #181

Closed gruyaume closed 2 weeks ago

gruyaume commented 2 weeks ago

Overview

We are getting an "UncaughtCharmError" when running a scenario test with a container that has a dash (-) in their name. In the example below, we are referring to pfcp-agent. It seems like scenario replaces the dash with an underscore.

Scenario test

def test_given_pfcp_service_not_running_when_collect_unit_status_then_status_is_waiting(self):
        self.mock_check_output.return_value = b"Flags: avx2 ssse3 fma cx16 rdrand"
        self.mock_client_list.return_value = []
        self.mock_multus_is_available.return_value = True
        self.mock_multus_is_ready.return_value = True
        gnb_subnet = "2.2.2.0/24"
        core_gateway_ip = "1.2.3.4"
        access_gateway_ip = "2.1.1.1"
        with tempfile.TemporaryDirectory() as temp_file:
            bessd_config_mount = scenario.Mount(
                location="/etc/bess/conf/",
                src=temp_file,
            )
            pfcp_agent_container = scenario.Container(
                name="pfcp-agent",
                can_connect=True,
            )
            bessd_container = scenario.Container(
                name="bessd",
                can_connect=True,
                mounts={
                    "config": bessd_config_mount,
                },
                layers={
                    "bessd": Layer({"services": {"bessd": {}, "routectl": {}}}),
                },
                service_status={"bessd": ServiceStatus.ACTIVE, "routectl": ServiceStatus.ACTIVE},
                exec_mock={
                    ("ip", "route", "show"): scenario.ExecOutput(
                        return_code=0,
                        stdout=f"default via {core_gateway_ip}\n {gnb_subnet} via {access_gateway_ip}",
                        stderr="",
                    ),
                    ("/opt/bess/bessctl/bessctl", "show", "version"): scenario.ExecOutput(
                        return_code=0,
                        stdout="",
                        stderr="",
                    ),
                    ("/opt/bess/bessctl/bessctl", "show", "worker"): scenario.ExecOutput(
                        return_code=0,
                        stdout="",
                        stderr="",
                    ),
                    ("/opt/bess/bessctl/bessctl", "show", "worker"): scenario.ExecOutput(
                        return_code=0,
                        stdout="RUNNING",
                        stderr="",
                    ),
                    ("/opt/bess/bessctl/bessctl", "show", "module", "accessRoutes"): scenario.ExecOutput(
                        return_code=0,
                        stdout="",
                        stderr="",
                    ),
                    ("/opt/bess/bessctl/bessctl", "show", "module", "coreRoutes"): scenario.ExecOutput(
                        return_code=0,
                        stdout="",
                        stderr="",
                    ),
                },
            )
            state_in = scenario.State(
                leader=True,
                containers=[bessd_container, pfcp_agent_container],
                config={
                    "core-gateway-ip": core_gateway_ip,
                    "access-gateway-ip": access_gateway_ip,
                    "gnb-subnet": gnb_subnet,
                },
            )

            state_out = self.ctx.run("collect_unit_status", state_in)

        assert state_out.unit_status == WaitingStatus("Waiting for pfcp agent service to run")

Charmcraft.yaml

name: sdcore-upf-k8s
summary: Charmed Operator for SD-Core's User Plane Function (UPF).
description: Charmed Operator for SD-Core's User Plane Function (UPF).
links:
  website:
    - https://charmhub.io/sdcore-upf-k8s
  source:
    - https://github.com/canonical/sdcore-upf-k8s-operator
  issues:
    - https://github.com/canonical/sdcore-upf-k8s-operator/issues

containers:
  bessd:
    resource: bessd-image
    mounts:
      - storage: config
        location: /etc/bess/conf/
      - storage: shared-app
        location: /pod-share/

  pfcp-agent:
    resource: pfcp-agent-image
    mounts:
      - storage: config
        location: /tmp/conf/
      - storage: shared-app
        location: /pod-share/

resources:
  bessd-image:
    type: oci-image
    description: OCI image for 5G upf bessd
    upstream-source: ghcr.io/canonical/sdcore-upf-bess:1.4.0

  pfcp-agent-image:
    type: oci-image
    description: OCI image for 5G upf pfcp-agent
    upstream-source: ghcr.io/canonical/sdcore-upf-pfcpiface:1.4.0

storage:
  config:
    type: filesystem
    minimum-size: 1M

  shared-app:
    type: filesystem
    minimum-size: 1M

provides:
  fiveg_n3:
    interface: fiveg_n3
  fiveg_n4:
    interface: fiveg_n4
  metrics-endpoint:
    interface: prometheus_scrape

requires:
  logging:
    interface: loki_push_api

assumes:
  - juju >= 3.4
  - k8s-api

type: charm
bases:
  - build-on:
    - name: ubuntu
      channel: "22.04"
    run-on:
    - name: ubuntu
      channel: "22.04"

parts:
  charm:
    build-packages:
      - cargo
      - libffi-dev
      - libssl-dev
      - pkg-config
      - rustc

config:
  options:
    cni-type:
      type: string
      default: bridge
      description: |
        Multus CNI plugin to use for the interfaces.
        Allowed values are `bridge`, `host-device`, `macvlan`, `vfioveth`.
    upf-mode:
      type: string
      default: af_packet
      description: |
        Either `af_packet` (default) or `dpdk`.
    dnn:
      type: string
      default: internet
      description: Data Network Name (DNN)
    gnb-subnet:
      type: string
      default: 192.168.251.0/24
      description: gNodeB subnet.
    access-interface:
      type: string
      description: Interface on the host to use for the Access Network.
    access-interface-mac-address:
      type: string
      description: |
        MAC address of the UPF's Access interface. 
        Required only if `upf-mode` is `dpdk`.
    access-ip:
      type: string
      default: 192.168.252.3/24
      description: IP address used by the UPF's Access interface.
    access-gateway-ip:
      type: string
      default: 192.168.252.1
      description: Gateway IP address to the Access Network.
    access-interface-mtu-size:
      type: int
      description: |
        MTU for the access interface (1200 <= MTU <= 65535) in bytes.
        If not specified, Multus will use its default value (typically 1500).
    core-interface:
      type: string
      description: Interface on the host to use for the Core Network.
    core-interface-mac-address:
      type: string
      description: |
        MAC address of the UPF's Core interface. 
        Required only if `upf-mode` is `dpdk`.
    core-ip:
      type: string
      default: 192.168.250.3/24
      description: IP address used by the UPF's Core interface.
    core-gateway-ip:
      type: string
      default: 192.168.250.1
      description: Gateway IP address to the Core Network.
    core-interface-mtu-size:
      type: int
      description: |
        MTU for the core interface (1200 <= MTU <= 65535) in bytes.
        If not specified, Multus will use its default value (typically 1500).
    external-upf-hostname:
      type: string
      description: |
        Externally accessible FQDN for the UPF.
        If not provided, it will default to the LoadBalancer Service hostname. 
        If that is not available, it will default to the internal
        Kubernetes FQDN of the service.
    enable-hw-checksum:
      type: boolean
      default: true
      description: |
        When enabled, hardware checksum will be used on the network interfaces.

Logs

scenario.runtime.UncaughtCharmError: Uncaught exception (<class 'RuntimeError'>) in operator/charm code: RuntimeError("container with name='pfcp_agent' not found. Did you forget a Container, or is the socket path '/charm/containers/pfcp_agent/pebble.socket' wrong?"
gruyaume commented 2 weeks ago

My bad, this was an error on my end