forked from istio-ecosystem/sail-operator
-
Notifications
You must be signed in to change notification settings - Fork 11
feat(library): Add pkg/install library for embedding Istio installation in external operators
#721
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
Merged
openshift-merge-bot
merged 41 commits into
openshift-service-mesh:main
from
aslakknutsen:sail_library_ossm
Mar 25, 2026
Merged
Changes from all commits
Commits
Show all changes
41 commits
Select commit
Hold shift + click to select a range
cd403bc
feat(install): add GetWatchSpecs for drift detection
aslakknutsen 9e63b66
feat(install): add Gateway API value helpers
aslakknutsen c80b95d
feat(crds): embed CRD YAML files for programmatic access
aslakknutsen 6c9bb4b
feat(install): add CRD management for Gateway API mode
aslakknutsen 6ac7ba6
refactor(install): use shared value computation pipeline
aslakknutsen 2a5efea
feat(install): add DriftReconciler for automatic drift detection
aslakknutsen 017d629
feat(install): add LibraryRBACRules for consumer RBAC aggregation
aslakknutsen 50e93f7
feat(install): auto-populate downstream image refs from embedded FS
aslakknutsen 0263fb4
feat(install): derive version from resource FS instead of versions.yaml
aslakknutsen bd2833b
refactor(install): replace manual MergeValues with generic map merge
aslakknutsen 2bd25cb
feat(install): add batch CRD ownership management and Status type
aslakknutsen 5821c6e
refactor(install)!: replace Installer+DriftReconciler with Library actor
aslakknutsen ff5c63c
feat(install): watch CRDs for ownership changes and lifecycle events
aslakknutsen bd13a1a
ix(install): resolve default version in getWatchSpecs
aslakknutsen 0e200c2
feat(install): add Status.String() for human-readable status output
aslakknutsen 733e978
feat(install): add structured logging to Library internals
aslakknutsen fdd3cc9
fix(install): reclaim CRDs with lost labels and reinstall deleted ones
aslakknutsen 80e4e90
fix(install): remove error retry loop from workqueue
aslakknutsen 45b94d2
refactor(install): extract CRDManager type and split filtering utilities
aslakknutsen 5de427d
fix(install): strip "v" prefix from image tags and normalize version …
aslakknutsen cb80b57
fix(install): deep-copy Values to prevent infinite reconcile loop
aslakknutsen 2ddbe94
refactor(install)!: remove OwnerRef and support Apply/Uninstall lifec…
aslakknutsen dd2ec6f
refactor(install): restructure package for clarity and fix race condi…
aslakknutsen 942be7f
test(install): add fake-client tests for crdManager
aslakknutsen e83768d
feat(install): use configurable managed-by label for Library resources
aslakknutsen e538d1a
fix(install)!: accept namespace/revision params in Uninstall for cras…
aslakknutsen d8bcbce
feat(install): allow consumer to adopt orphaned OLM-managed CRDs
aslakknutsen 72bf038
feat(install): add Enqueue() to force reconciliation on external stat…
aslakknutsen bd10b40
fix(install): prevent panic on double Uninstall by niling closed chan…
aslakknutsen 2cefc40
fix(install): add exponential backoff on failed reconciliations
aslakknutsen 50152cb
fix(install): fix Uninstall deadlock caused by niled processingDone c…
aslakknutsen f1067e9
docs(install): add README and fix source.Channel usage in USAGE.md
aslakknutsen ebc5039
feat(install): load image digests from embedded CSV annotations
aslakknutsen 1efbbf7
fix(install): clear status after successful Uninstall
aslakknutsen b3c6688
fix(embed): update embed csv ref to match downstream
aslakknutsen 57c3abf
fix: remove unused default values and deprecated api refs
aslakknutsen e70288b
refactor(bundle): move CSV embed out of bundle/manifests to avoid ope…
aslakknutsen 2e8a2d0
fix: lint stuff
aslakknutsen 385d509
fix: lint stuff
aslakknutsen fcd3fe5
fix: make gen go.mod updates
aslakknutsen 4159c7d
fix(install): align clearIgnoredFields with upstream webhook predicate
aslakknutsen File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| // Copyright Istio Authors | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| package bundle | ||
|
|
||
| import _ "embed" | ||
|
|
||
| //go:embed manifests/servicemeshoperator3.clusterserviceversion.yaml | ||
| var CSV []byte | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| // Copyright Istio Authors | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| // Package crds provides embedded CRD YAML files for Istio and Sail resources. | ||
| package crds | ||
|
|
||
| import "embed" | ||
|
|
||
| // FS contains all CRD YAML files from the chart/crds directory. | ||
| // This allows programmatic access to CRDs for installation. | ||
| // | ||
| // CRD files follow the naming convention: {group}_{plural}.yaml | ||
| // Example: extensions.istio.io_wasmplugins.yaml | ||
| // | ||
| //go:embed *.yaml | ||
| var FS embed.FS |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| # pkg/install | ||
|
|
||
| Library for managing istiod installations without running the Sail Operator. | ||
| Designed for embedding in other operators (e.g. OpenShift Ingress) that need | ||
| to install and maintain Istio as an internal dependency. | ||
|
|
||
| ## Usage | ||
|
|
||
| ```go | ||
| lib, err := install.New(kubeConfig, resourceFS) | ||
| notifyCh := lib.Start(ctx) | ||
|
|
||
| // In controller reconcile: | ||
| lib.Apply(install.Options{ | ||
| Namespace: "istio-system", | ||
| Values: install.GatewayAPIDefaults(), | ||
| }) | ||
|
|
||
| // Read result after notification: | ||
| for range notifyCh { | ||
| status := lib.Status() | ||
| // update conditions from status | ||
| } | ||
|
|
||
| // Teardown: | ||
| lib.Uninstall(ctx, "istio-system", "default") | ||
| ``` | ||
|
|
||
| ## How it works | ||
|
|
||
| The Library runs as an independent actor with a simple state model: | ||
|
|
||
| 1. **Apply** -- consumer sends desired state (version, namespace, values) | ||
| 2. **Reconcile** -- Library installs/upgrades CRDs and istiod via Helm | ||
| 3. **Drift detection** -- dynamic informers watch owned resources and CRDs, re-enqueuing reconciliation on changes | ||
| 4. **Status** -- consumer reads the reconciliation result | ||
|
|
||
| The reconciliation loop sits idle until the first `Apply()` call. After that, | ||
| it stays active with informers running until `Uninstall()` clears the desired | ||
| state and stops the loop. | ||
|
|
||
| ## Public API | ||
|
|
||
| ### Constructor | ||
|
|
||
| - `New(kubeConfig, resourceFS)` -- creates a Library with Kubernetes clients, Helm chart manager, and CRD manager | ||
| - `FromDirectory(path)` -- creates an `fs.FS` from a filesystem path (alternative to embedded resources) | ||
|
|
||
| ### Library methods | ||
|
|
||
| | Method | Description | | ||
| |---|---| | ||
| | `Start(ctx)` | Starts the reconciliation loop; returns a notification channel | | ||
| | `Apply(opts)` | Sets desired state; enqueues reconciliation if changed | | ||
| | `Enqueue()` | Forces re-reconciliation without changing desired state | | ||
| | `Status()` | Returns the latest reconciliation result | | ||
| | `Uninstall(ctx, ns, rev)` | Stops informers, waits for processing, then Helm-uninstalls | | ||
|
|
||
| ### Types | ||
|
|
||
| - **Options** -- install options: `Namespace`, `Version`, `Revision`, `Values`, `ManageCRDs`, `IncludeAllCRDs`, `OverwriteOLMManagedCRD` | ||
| - **Status** -- reconciliation result: `CRDState`, `CRDMessage`, `CRDs`, `Installed`, `Version`, `Error` | ||
| - **CRDManagementState** -- aggregate CRD ownership: `ManagedByCIO`, `ManagedByOLM`, `UnknownManagement`, `MixedOwnership`, `NoneExist` | ||
| - **CRDInfo** -- per-CRD state: `Name`, `State`, `Found` | ||
| - **ImageNames** -- image names for each component: `Istiod`, `Proxy`, `CNI`, `ZTunnel` | ||
|
|
||
| ### Helper functions | ||
|
|
||
| - `GatewayAPIDefaults()` -- pre-configured values for Gateway API mode on OpenShift | ||
| - `MergeValues(base, overlay)` -- deep-merge two Values structs (overlay wins) | ||
| - `DefaultVersion(resourceFS)` -- highest stable semver version from the resource FS | ||
| - `NormalizeVersion(version)` -- ensures a `v` prefix | ||
| - `ValidateVersion(resourceFS, version)` -- checks that a version directory exists | ||
| - `SetImageDefaults(resourceFS, registry, images)` -- populates image refs from version directories | ||
| - `LibraryRBACRules()` -- returns RBAC PolicyRules for a consumer's ClusterRole | ||
|
|
||
| ## CRD management | ||
|
|
||
| The Library classifies existing CRDs by ownership labels before deciding what to do: | ||
|
|
||
| | State | Meaning | Action | | ||
| |---|---|---| | ||
| | `NoneExist` | No target CRDs on cluster | Install with CIO labels | | ||
| | `ManagedByCIO` | All owned by Cluster Ingress Operator | Update as needed | | ||
| | `ManagedByOLM` | All owned by OLM (OSSM subscription) | Leave alone; Helm install proceeds | | ||
| | `UnknownManagement` | CRDs exist without recognized labels | Leave alone; set Status.Error | | ||
| | `MixedOwnership` | Inconsistent labels across CRDs | Leave alone; set Status.Error | | ||
|
|
||
| The `OverwriteOLMManagedCRD` callback in Options lets the consumer decide | ||
| whether to take over OLM-managed CRDs (e.g. after an OSSM subscription is deleted). | ||
|
|
||
| Which CRDs are targeted depends on `IncludeAllCRDs`: when false (default), only | ||
| CRDs matching `PILOT_INCLUDE_RESOURCES` / `PILOT_IGNORE_RESOURCES` are managed. | ||
|
|
||
| ## Files | ||
|
|
||
| | File | Purpose | | ||
| |---|---| | ||
| | `library.go` | Public API, types (`Library`, `Status`, `Options`), constructor | | ||
| | `lifecycle.go` | Reconciliation loop, workqueue, `Start`/`Apply`/`Uninstall` | | ||
| | `installer.go` | Core install/uninstall logic, Helm values resolution, watch spec extraction | | ||
| | `crds.go` | CRD ownership classification, install, update | | ||
| | `crds_filter.go` | CRD selection based on `PILOT_INCLUDE_RESOURCES` / `PILOT_IGNORE_RESOURCES` | | ||
| | `values.go` | `GatewayAPIDefaults()`, `MergeValues()` | | ||
| | `predicates.go` | Event filtering for informers (ownership checks, status-only changes) | | ||
| | `informers.go` | Dynamic informer setup for drift detection | | ||
| | `version.go` | Version resolution and validation | | ||
| | `images.go` | Image configuration from resource FS | | ||
| | `rbac.go` | RBAC rules for library consumers | |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is generated after compilation so it might embed outdated version IIUC. This looks quite dangerous.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For context, it broke our upstream sync job which is removing generated files in the bundle dir before running
make genThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@FilipB The Library that reads this is imported via Source, not as a binary. We'll tag the "source release" after the CSV has been updated with the latest SHAs from the binary builds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@FilipB Sorry for breaking the job. If you can make an exception to the delete that would be great. Else I can technically move that file up one level, but that require some code changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No worries. Just to be clear, there is no need to move
bundle/bundle.gofile, it fails on:ERROR: exit status 1: bundle/bundle.go:19:12: pattern manifests/servicemeshoperator3.clusterserviceversion.yaml: no matching files foundas we dorm -rf bundle/**/*.yamlbefore runningmake genThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, it's actually failing on
make mirror-licenseswhich is part ofgentarget. I thought it fails during compilation.