---
# System prepended metadata

title: Channel elections with no/multiple heads
tags: [fbc]

---

---
tags: fbc
title: Channel elections with no/multiple heads
---

# Channel elections with no/multiple heads

As discussed in slack (this thread: https://redhat-internal.slack.com/archives/GHMALGJV6/p1678437956935269), I'm setting up an initial discussion so we can identify the big questions/issues we want to tackle in follow-up sessions.  

That thread resulted in creation of an epic to crystallize discussion around ([OPRUN-2905](https://issues.redhat.com/browse/OPRUN-2905)). 

## Background
Combined with a bug in SQLite-based `opm index add` that truncated skips-of-skips during successive bundle additions to a channel, and `oc mirror` usage which decapitated the current channel head, produced a channel composed of multiple, unrelated bundles.  This appears to the OLM resolver to be a channel with multiple heads, which is forbidden/unsupported.

*Crux*:  `oc mirror` runs `opm validate` on the graph resulting from the mirror operation, and fails.  How can we avoid this?  How can we present a arbitrary 'correct' subgraph?  Cincinatti does this.  (How do they identify which head to follow? How do they solve the 'stranding' issue? Or do they not solve the problem and just make it more visible to folks when they have loaded a footgun?)


### SQLite desired graph
accumulates transitive edges without loss from bundles' CSVs
```mermaid
graph RL
  %% package "kubernetes-nmstate-operator"
  subgraph "kubernetes-nmstate-operator"
    %% channel "stable"
    subgraph stable
      kubernetes-nmstate-operator.4.12.0-202301241446
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202209060257
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202212061458
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202211081106
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202211032036
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202210052203
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202301241446
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202301091615
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202211110827
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202301102156
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202212060046
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202212151001
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202301171525
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202211220137
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202301051925
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202209060445
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202210251038
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202209130958
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202210031619
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202301061555
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202301171655
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202212151222
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202212050849
      kubernetes-nmstate-operator.4.12.0-202302061702 -- skip --> kubernetes-nmstate-operator.4.12.0-202301042354
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202209060257
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202212060046
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202210052203
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202301051925
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202301042354
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202212061458
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202210031619
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202301171525
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202211220137
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202301091615
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202301241446
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202212050849
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202302061702
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202211032036
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202301102156
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202210251038
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202212151222
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202209130958
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202209060445
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202301171655
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202211110827
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202301061555
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202212151001
      kubernetes-nmstate-operator.4.12.0-202302171855 -- skip --> kubernetes-nmstate-operator.4.12.0-202211081106
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202210251038
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202302061702
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202211081106
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202301102156
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202210052203
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202211220137
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202301171525
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202301171655
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202209130958
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202301061555
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202211110827
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202301091615
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202301241446
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202301042354
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202301051925
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202212151001
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202210031619
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202209060445
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202212151222
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202209060257
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202302171855
      kubernetes-nmstate-operator.4.12.0-202302280915 -- skip --> kubernetes-nmstate-operator.4.12.0-202212061458
    end

  end

```


### SQLite buggy graph
discards edges which are 'duplicated' as it rebuilds the graph from tail to head for each new addition
```mermaid
graph LR
  %% package "kubernetes-nmstate-operator"
  subgraph "kubernetes-nmstate-operator"
    %% channel "stable"
    subgraph kubernetes-nmstate-operator-stable["stable"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202301241446["kubernetes-nmstate-operator.4.12.0-202301241446"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202211220137["kubernetes-nmstate-operator.4.12.0-202211220137"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202211110827["kubernetes-nmstate-operator.4.12.0-202211110827"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202301051925["kubernetes-nmstate-operator.4.12.0-202301051925"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202212151001["kubernetes-nmstate-operator.4.12.0-202212151001"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302171855["kubernetes-nmstate-operator.4.12.0-202302171855"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202301171655["kubernetes-nmstate-operator.4.12.0-202301171655"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202301241446["kubernetes-nmstate-operator.4.12.0-202301241446"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202212061458["kubernetes-nmstate-operator.4.12.0-202212061458"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302061702["kubernetes-nmstate-operator.4.12.0-202302061702"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202301171525["kubernetes-nmstate-operator.4.12.0-202301171525"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202301061555["kubernetes-nmstate-operator.4.12.0-202301061555"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202301091615["kubernetes-nmstate-operator.4.12.0-202301091615"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202210031619["kubernetes-nmstate-operator.4.12.0-202210031619"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202212151222["kubernetes-nmstate-operator.4.12.0-202212151222"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202210251038["kubernetes-nmstate-operator.4.12.0-202210251038"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202211081106["kubernetes-nmstate-operator.4.12.0-202211081106"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202301102156["kubernetes-nmstate-operator.4.12.0-202301102156"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202210052203["kubernetes-nmstate-operator.4.12.0-202210052203"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202209130958["kubernetes-nmstate-operator.4.12.0-202209130958"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202301042354["kubernetes-nmstate-operator.4.12.0-202301042354"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202209060445["kubernetes-nmstate-operator.4.12.0-202209060445"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
      kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202209060257["kubernetes-nmstate-operator.4.12.0-202209060257"]-- skip --> kubernetes-nmstate-operator-stable-kubernetes-nmstate-operator.4.12.0-202302280915["kubernetes-nmstate-operator.4.12.0-202302280915"]
    end
  end
```


### Discussion Topics


Decouple edge definition from channels?

- lost the thread while trying to capture other details here.  Maintaining two collections and rectifying them during resolution feels like at attempt at solving the abstract problem, maybe?

Avoidable heuristic when stranded in multiple-heads-land?
- Inadequate, because selection of a tail could result, stranding the customer (just changing problem)
- Is this solved if we prefer heads in semver order where there are multiple?



### Summary of 3/30 meeting
- imperative opm command behavior changes off the table (`opm registry add` / `opm index add`), but any solution which doesn't include changes to these commands will be incomplete on its face
- scenario trivially replicable in FBC anyway
- still in brainstorming mode
- oc-mirror now in permanent team
- **next meeting** to loop in OLM team so we can talk possible solution space (ecosystem + runtime reps)
- **meeting after** to loop in CFE (oc-mirror) team
   - oc-mirror folks more of an API client (may not be conversant with OLM-side logic)

