|
| 1 | +// Variables embedded for GitHub compatibility |
| 2 | +:istio_latest_version: 1.26.3 |
| 3 | +:istio_latest_version_revision_format: 1-26-3 |
| 4 | +:istio_latest_tag: v1.26-latest |
| 5 | +:istio_latest_minus_one_version: 1.26.2 |
| 6 | +:istio_latest_minus_one_version_revision_format: 1-26-2 |
| 7 | + |
| 8 | +link:../[Return to Project Root] |
| 9 | + |
| 10 | +*Note*: To add new topics to this documentation, please follow the guidelines in the link:../../docs/guidelines/guidelines.md[guidelines] doc. |
| 11 | + |
| 12 | +== Table of Contents |
| 13 | + |
| 14 | +* <<user-documentation>> |
| 15 | +* <<concepts>> |
| 16 | +** <<istio-resource>> |
| 17 | +** link:general/istiod-ha.adoc#running-istiod-in-ha-mode[Istiod in HA mode] |
| 18 | +*** link:general/istiod-ha.adoc#setting-up-istiod-in-ha-mode-increasing-replicacount[Setting up Istiod in HA mode: using fixed replicas] |
| 19 | +*** link:general/istiod-ha.adoc#setting-up-istiod-in-ha-mode-using-autoscaling[Setting up Istiod in HA mode: using autoscaling] |
| 20 | +** <<istiorevision-resource>> |
| 21 | +** <<istiorevisiontag-resource>> |
| 22 | +** <<istiocni-resource>> |
| 23 | +*** <<updating-the-istiocni-resource>> |
| 24 | +** <<resource-status>> |
| 25 | +*** <<inuse-detection>> |
| 26 | +* <<api-reference-documentation>> |
| 27 | +* link:general/getting-started.adoc#getting-started[Getting Started] |
| 28 | +** link:general/getting-started.adoc#installation-on-openshift[Installation on OpenShift] |
| 29 | +** link:general/getting-started.adoc#installation-from-source[Installation from Source] |
| 30 | +** link:general/getting-started.adoc#migrating-from-istio-in-cluster-operator[Migrating from Istio in-cluster Operator] |
| 31 | +*** link:general/getting-started.adoc#setting-environments-variables-for-istiod[Setting environments variables for Istiod] |
| 32 | +*** link:general/getting-started.adoc#components-field[Components field] |
| 33 | +*** link:general/getting-started.adoc#cni-lifecycle-management[CNI lifecycle management] |
| 34 | +*** link:general/getting-started.adoc#converter-script-to-migrate-istio-in-cluster-operator-configuration-to-sail-operator[Converter Script to Migrate Istio in-cluster Operator Configuration to Sail Operator] |
| 35 | +* link:common/create-and-configure-gateways.adoc#creating-and-configuring-gateways[Creating and Configuring Gateways] |
| 36 | +** link:common/create-and-configure-gateways.adoc#option-1-istio-gateway-injection[Option 1: Istio Gateway Injection] |
| 37 | +** link:common/create-and-configure-gateways.adoc#option-2-kubernetes-gateway-api[Option 2: Kubernetes Gateway API] |
| 38 | +* link:update-strategy/update-strategy.adoc#update-strategy[Update Strategy] |
| 39 | +** link:update-strategy/update-strategy.adoc#inplace[InPlace] |
| 40 | +*** link:update-strategy/update-strategy.adoc#example-using-the-inplace-strategy[Example using the InPlace strategy] |
| 41 | +*** link:update-strategy/update-strategy.adoc#recommendations-for-inplace-strategy[Recommendations for InPlace strategy] |
| 42 | +** link:update-strategy/update-strategy.adoc#revisionbased[RevisionBased] |
| 43 | +*** link:update-strategy/update-strategy.adoc#example-using-the-revisionbased-strategy[Example using the RevisionBased strategy] |
| 44 | +*** link:update-strategy/update-strategy.adoc#example-using-the-revisionbased-strategy-and-an-istiorevisiontag[Example using the RevisionBased strategy and an IstioRevisionTag] |
| 45 | +* link:deployment-models/multiple-mesh.adoc#multiple-meshes-on-a-single-cluster[Multiple meshes on a single cluster] |
| 46 | +** link:deployment-models/multiple-mesh.adoc#prerequisites[Prerequisites] |
| 47 | +** link:deployment-models/multiple-mesh.adoc#installation-steps[Installation Steps] |
| 48 | +*** link:deployment-models/multiple-mesh.adoc#deploying-the-control-planes[Deploying the control planes] |
| 49 | +*** link:deployment-models/multiple-mesh.adoc#deploying-the-applications[Deploying the applications] |
| 50 | +** link:deployment-models/multiple-mesh.adoc#validation[Validation] |
| 51 | +*** link:deployment-models/multiple-mesh.adoc#checking-application-to-control-plane-mapping[Checking application to control plane mapping] |
| 52 | +*** link:deployment-models/multiple-mesh.adoc#checking-application-connectivity[Checking application connectivity] |
| 53 | +** link:deployment-models/consolidating-cp.adoc[Consolidating control planes] |
| 54 | +* link:deployment-models/multicluster.adoc#multi-cluster[Multi-cluster] |
| 55 | +** link:deployment-models/multicluster.adoc#prerequisites[Prerequisites] |
| 56 | +** link:deployment-models/multicluster.adoc#common-setup[Common Setup] |
| 57 | +** link:deployment-models/multicluster.adoc#multi-primary-multi-network[Multi-Primary] |
| 58 | +** link:deployment-models/multicluster.adoc#primary-remote-multi-network[Primary-Remote] |
| 59 | +** link:deployment-models/multicluster.adoc#external-control-plane[External Control Plane] |
| 60 | +* link:dual-stack/dual-stack.adoc#dual-stack-support[Dual-stack Support] |
| 61 | +** link:dual-stack/dual-stack.adoc#prerequisites[Prerequisites] |
| 62 | +** link:dual-stack/dual-stack.adoc#installation-steps[Installation Steps] |
| 63 | +** link:dual-stack/dual-stack.adoc#validation[Validation] |
| 64 | +* link:common/istio-ambient-mode.adoc#introduction-to-istio-ambient-mode[Introduction to Istio Ambient mode] |
| 65 | +** link:common/istio-ambient-mode.adoc#component-version[Component version] |
| 66 | +** link:common/istio-ambient-mode.adoc#concepts[Concepts] |
| 67 | +*** link:common/istio-ambient-mode.adoc#ztunnel-resource[ZTunnel resource] |
| 68 | +*** link:common/istio-ambient-mode.adoc#api-reference-documentation[API Reference documentation] |
| 69 | +** link:common/istio-ambient-mode.adoc#core-features[Core features] |
| 70 | +** link:common/istio-ambient-mode.adoc#getting-started[Getting Started] |
| 71 | +** link:common/istio-ambient-mode.adoc#visualize-the-application-using-kiali-dashboard[Visualize the application using Kiali dashboard] |
| 72 | +** link:common/istio-ambient-mode.adoc#troubleshoot-issues[Troubleshoot issues] |
| 73 | +** link:common/istio-ambient-mode.adoc#cleanup[Cleanup] |
| 74 | +* link:common/istio-ambient-update.adoc#updating-istio-in-ambient-mode[Updating Istio in Ambient Mode] |
| 75 | +** link:common/istio-ambient-update.adoc#understanding-versioning[Understanding versioning] |
| 76 | +** link:common/istio-ambient-update.adoc#about-inplace-strategy[About InPlace strategy] |
| 77 | +** link:common/istio-ambient-update.adoc#about-revisionbased-strategy[About RevisionBased strategy] |
| 78 | +** link:common/istio-ambient-update.adoc#common-update-procedures-for-ambient-components[Common Update Procedures for Ambient Components] |
| 79 | +** link:common/istio-ambient-update.adoc#special-considerations-for-ambient-mode-upgrades[Special Considerations for Ambient Mode Upgrades] |
| 80 | +* link:common/istio-ambient-waypoint.adoc#introduction-to-istio-waypoint-proxy[Introduction to Istio Waypoint Proxy] |
| 81 | +** link:common/istio-ambient-waypoint.adoc#core-features[Core features] |
| 82 | +** link:common/istio-ambient-waypoint.adoc#getting-started[Getting Started] |
| 83 | +** link:common/istio-ambient-waypoint.adoc#update[Update] |
| 84 | +** link:common/istio-ambient-waypoint.adoc#layer-7-features-in-ambient-mode[Layer 7 Features in Ambient Mode] |
| 85 | +** link:common/istio-ambient-waypoint.adoc#troubleshoot-issues[Troubleshoot issues] |
| 86 | +** link:common/istio-ambient-waypoint.adoc#cleanup[Cleanup] |
| 87 | +* link:addons/addons.adoc#addons[Addons] |
| 88 | +** link:addons/addons.adoc#deploy-prometheus-and-jaeger-addons[Deploy Prometheus and Jaeger addons] |
| 89 | +** link:addons/addons.adoc#deploy-kiali-addon[Deploy Kiali addon] |
| 90 | +** link:addons/addons.adoc#find-the-active-revision-of-your-istio-instance[Find the active revision of your Istio instance. In our case it is `test`.] |
| 91 | +** link:addons/addons.adoc#deploy-gateway-and-bookinfo[Deploy Gateway and Bookinfo] |
| 92 | +** link:addons/addons.adoc#generate-traffic-and-visualize-your-mesh[Generate traffic and visualize your mesh] |
| 93 | +* link:addons/observability.adoc#observability-integrations[Observability Integrations] |
| 94 | +** link:addons/observability.adoc#scraping-metrics-using-the-openshift-monitoring-stack[Scraping metrics using the OpenShift monitoring stack] |
| 95 | +** link:addons/observability.adoc#configure-tracing-with-openshift-distributed-tracing[Configure tracing with OpenShift distributed tracing] |
| 96 | +** link:addons/observability.adoc#integrating-with-kiali[Integrating with Kiali] |
| 97 | +*** link:addons/observability.adoc#integrating-kiali-with-the-openshift-monitoring-stack[Integrating Kiali with the OpenShift monitoring stack] |
| 98 | +*** link:addons/observability.adoc#integrating-kiali-with-openshift-distributed-tracing[Integrating Kiali with OpenShift Distributed Tracing] |
| 99 | +* Certificates management |
| 100 | +** link:general/plugin-ca.adoc[Plug in CA Certificates] |
| 101 | +* link:general/getting-started.adoc#uninstalling[Uninstalling] |
| 102 | +** link:general/getting-started.adoc#deleting-istio[Deleting Istio] |
| 103 | +** link:general/getting-started.adoc#deleting-istiocni[Deleting IstioCNI] |
| 104 | +** link:general/getting-started.adoc#deleting-the-sail-operator[Deleting the Sail Operator] |
| 105 | +** link:general/getting-started.adoc#deleting-the-istio-system-and-istio-cni-projects[Deleting the istio-system and istio-cni Projects] |
| 106 | +** link:general/getting-started.adoc#decide-whether-you-want-to-delete-the-crds-as-well[Decide whether you want to delete the CRDs as well] |
| 107 | + |
| 108 | +[#user-documentation] |
| 109 | +== User Documentation |
| 110 | + |
| 111 | +Sail Operator manages the lifecycle of your Istio control planes. Instead of creating a new configuration schema, Sail Operator APIs are built around Istio's helm chart APIs. All installation and configuration options that are exposed by Istio's helm charts are available through the Sail Operator CRDs' `values` fields. |
| 112 | + |
| 113 | +Similar to using Istio's Helm charts, the final set of values used to render the charts is determined by a combination of user-provided values, default chart values, and values from selected profiles. |
| 114 | +These profiles can include the user-defined profile, the platform profile, and the compatibility version profile. |
| 115 | +To view the final set of values, inspect the ConfigMap named `values` (or `values-<revision>`) in the namespace where the control plane is installed. |
| 116 | + |
| 117 | +[#concepts] |
| 118 | +== Concepts |
| 119 | + |
| 120 | +[#istio-resource] |
| 121 | +=== Istio resource |
| 122 | + |
| 123 | +The `Istio` resource is used to manage your Istio control planes. It is a cluster-wide resource, as the Istio control plane operates in and requires access to the entire cluster. To select a namespace to run the control plane pods in, you can use the `spec.namespace` field. Note that this field is immutable, though: in order to move a control plane to another namespace, you have to remove the Istio resource and recreate it with a different `spec.namespace`. You can access all helm chart options through the `values` field in the `spec`: |
| 124 | + |
| 125 | +[source,yaml] |
| 126 | +---- |
| 127 | +apiVersion: sailoperator.io/v1 |
| 128 | +kind: Istio |
| 129 | +metadata: |
| 130 | + name: default |
| 131 | +spec: |
| 132 | + namespace: istio-system |
| 133 | + updateStrategy: |
| 134 | + type: InPlace |
| 135 | + values: |
| 136 | + pilot: |
| 137 | + resources: |
| 138 | + requests: |
| 139 | + cpu: 100m |
| 140 | + memory: 1024Mi |
| 141 | +---- |
| 142 | + |
| 143 | +Note: If you need a specific Istio version, you can explicitly set it using `spec.version`. If not specified, the Operator will install the latest supported version. |
| 144 | + |
| 145 | +Istio uses a ConfigMap for its global configuration, called the MeshConfig. All of its settings are available through `spec.meshConfig`. |
| 146 | + |
| 147 | +To support canary updates of the control plane, Sail Operator includes support for multiple Istio versions. You can select a version by setting the `version` field in the `spec` to the version you would like to install, prefixed with a `v`. You can then update to a new version just by changing this field. An `vX.Y-latest` alias can be used for the latest z/patch versions of each supported y/minor versions. As per the example above, `{istio_latest_tag}` can be specified in the `version` field. By doing so, the operator will keep the istio version with the latest `z` version of the same `y` version. |
| 148 | + |
| 149 | +Sail Operator supports two different update strategies for your control planes: `InPlace` and `RevisionBased`. When using `InPlace`, the operator will immediately replace your existing control plane resources with the ones for the new version, whereas `RevisionBased` uses Istio's canary update mechanism by creating a second control plane to which you can migrate your workloads to complete the update. |
| 150 | + |
| 151 | +After creation of an `Istio` resource, the Sail Operator will generate a revision name for it based on the updateStrategy that was chosen, and create a corresponding <<istiorevision-resource>>. |
| 152 | + |
| 153 | +[#istiorevision-resource] |
| 154 | +=== IstioRevision resource |
| 155 | + |
| 156 | +The `IstioRevision` is the lowest-level API the Sail Operator provides, and it is usually not created by the user, but by the operator itself. It's schema closely resembles that of the `Istio` resource - but instead of representing the state of a control plane you want to be present in your cluster, it represents a *revision* of that control plane, which is an instance of Istio with a specific version and revision name, and its revision name can be used to add workloads or entire namespaces to the mesh, e.g. by using the `istio.io/rev=<REVISION_NAME>` label. It is also a cluster-wide resource. |
| 157 | + |
| 158 | +You can think of the relationship between the `Istio` and `IstioRevision` resource as similar to the one between Kubernetes' `ReplicaSet` and `Pod`: a `ReplicaSet` can be created by users and results in the automatic creation of `Pods`, which will trigger the instantiation of your containers. Similarly, users create an `Istio` resource which instructs the operator to create a matching `IstioRevision`, which then in turn triggers the creation of the Istio control plane. To do that, the Sail Operator will copy all of your relevant configuration from the `Istio` resource to the `IstioRevision` resource. |
| 159 | + |
| 160 | +[#istiorevisiontag-resource] |
| 161 | +=== IstioRevisionTag resource |
| 162 | + |
| 163 | +The `IstioRevisionTag` resource represents a *Stable Revision Tag*, which functions as an alias for Istio control plane revisions. With a stable tag `prod`, you can e.g. use the label `istio.io/rev=prod` to inject proxies into your workloads. When you perform an upgrade to a control plane with a new revision name, you can simply update your tag to point to the new revision, instead of having to re-label your workloads and namespaces. Also see the https://istio.io/latest/docs/setup/upgrade/canary/#stable-revision-labels[Stable Revision Tags] section of Istio's https://istio.io/latest/docs/setup/upgrade/canary/[Canary Upgrades documentation] for more details. |
| 164 | + |
| 165 | +In Istio, stable revision tags are usually created using `istioctl`, but if you're using the Sail Operator, you can use the `IstioRevisionTag` resource, which comes with an additional feature: instead of just being able to reference an `IstioRevision`, you can also reference an `Istio` resource. When you now update your control plane and the underlying `IstioRevision` changes, the Sail Operator will update your revision tag for you. You only need to restart your deployments to re-inject the new proxies. |
| 166 | + |
| 167 | +[source,yaml] |
| 168 | +---- |
| 169 | +apiVersion: sailoperator.io/v1 |
| 170 | +kind: IstioRevisionTag |
| 171 | +metadata: |
| 172 | + name: default |
| 173 | +spec: |
| 174 | + targetRef: |
| 175 | + kind: Istio # can be either Istio or IstioRevision |
| 176 | + name: prod # the name of the Istio/IstioRevision resource |
| 177 | +---- |
| 178 | + |
| 179 | +As you can see in the YAML above, `IstioRevisionTag` really only has one field in its spec: `targetRef`. With this field, you can reference an `Istio` or `IstioRevision` resource. So after deploying this, you will be able to use both the `istio.io/rev=default` and also `istio-injection=enabled` labels to inject proxies into your workloads. The `istio-injection` label can only be used for revisions and revision tags named `default`, like the `IstioRevisionTag` in the above example. |
| 180 | + |
| 181 | +[#istiocni-resource] |
| 182 | +=== IstioCNI resource |
| 183 | + |
| 184 | +The lifecycle of Istio's CNI plugin is managed separately when using Sail Operator. To install it, you can create an `IstioCNI` resource. The `IstioCNI` resource is a cluster-wide resource as it will install a `DaemonSet` that will be operating on all nodes of your cluster. |
| 185 | + |
| 186 | +[source,yaml] |
| 187 | +---- |
| 188 | +apiVersion: sailoperator.io/v1 |
| 189 | +kind: IstioCNI |
| 190 | +metadata: |
| 191 | + name: default |
| 192 | +spec: |
| 193 | + namespace: istio-cni |
| 194 | + values: |
| 195 | + cni: |
| 196 | + cniConfDir: /etc/cni/net.d |
| 197 | + excludeNamespaces: |
| 198 | + - kube-system |
| 199 | +---- |
| 200 | + |
| 201 | +[NOTE] |
| 202 | +==== |
| 203 | +If you need a specific Istio version, you can explicitly set it using `spec.version`. If not specified, the Operator will install the latest supported version. |
| 204 | +==== |
| 205 | + |
| 206 | +[#updating-the-istiocni-resource] |
| 207 | +==== Updating the IstioCNI resource |
| 208 | + |
| 209 | +Updates for the `IstioCNI` resource are `Inplace` updates, this means that the `DaemonSet` will be updated with the new version of the CNI plugin once the resource is updated and the `istio-cni-node` pods are going to be replaced with the new version. |
| 210 | +To update the CNI plugin, just change the `version` field to the version you want to install. Just like the `Istio` resource, it also has a `values` field that exposes all of the options provided in the `istio-cni` chart: |
| 211 | + |
| 212 | +. Create the `IstioCNI` resource. |
| 213 | ++ |
| 214 | +[source,bash,subs="attributes+",,name="cni-update-test"] |
| 215 | +---- |
| 216 | +kubectl create ns istio-cni |
| 217 | +cat <<EOF | kubectl apply -f- |
| 218 | +apiVersion: sailoperator.io/v1 |
| 219 | +kind: IstioCNI |
| 220 | +metadata: |
| 221 | + name: default |
| 222 | +spec: |
| 223 | + version: v{istio_latest_minus_one_version} |
| 224 | + namespace: istio-cni |
| 225 | + values: |
| 226 | + cni: |
| 227 | + cniConfDir: /etc/cni/net.d |
| 228 | + excludeNamespaces: |
| 229 | + - kube-system |
| 230 | +EOF |
| 231 | +---- |
| 232 | + |
| 233 | +ifdef::cni-update-test[] |
| 234 | +wait_cni_ready "istio-cni" |
| 235 | +with_retries resource_version_equal "istiocni" "default" "v{istio_latest_minus_one_version}" |
| 236 | +endif::[] |
| 237 | + |
| 238 | +. Confirm the installation and version of the CNI plugin. |
| 239 | ++ |
| 240 | +[source,console,subs="attributes+"] |
| 241 | +---- |
| 242 | +$ kubectl get istiocni -n istio-cni |
| 243 | +NAME READY STATUS VERSION AGE |
| 244 | +default True Healthy v{istio_latest_minus_one_version} 91m |
| 245 | +$ kubectl get pods -n istio-cni |
| 246 | +NAME READY STATUS RESTARTS AGE |
| 247 | +istio-cni-node-hd9zf 1/1 Running 0 90m |
| 248 | +---- |
| 249 | + |
| 250 | +ifdef::cni-update-test[] |
| 251 | +print_cni_info |
| 252 | +endif::[] |
| 253 | + |
| 254 | +. Update the CNI plugin version. |
| 255 | ++ |
| 256 | +[source,bash,subs="attributes+",name="cni-update-test"] |
| 257 | +---- |
| 258 | +kubectl patch istiocni default -n istio-cni --type='merge' -p '{"spec":{"version":"v{istio_latest_version}"}}' |
| 259 | +---- |
| 260 | + |
| 261 | +ifdef::cni-update-test[] |
| 262 | +with_retries resource_version_equal "istiocni" "default" "v{istio_latest_version}" |
| 263 | +wait_cni_ready "istio-cni" |
| 264 | +endif::[] |
| 265 | + |
| 266 | +. Confirm the CNI plugin version was updated. |
| 267 | ++ |
| 268 | +[source,console,subs="attributes+"] |
| 269 | +---- |
| 270 | +$ kubectl get istiocni -n istio-cni |
| 271 | +NAME READY STATUS VERSION AGE |
| 272 | +default True Healthy v{istio_latest_version} 93m |
| 273 | +$ kubectl get pods -n istio-cni |
| 274 | +NAME READY STATUS RESTARTS AGE |
| 275 | +istio-cni-node-jz4lg 1/1 Running 0 44s |
| 276 | +---- |
| 277 | + |
| 278 | +ifdef::cni-update-test[] |
| 279 | +print_cni_info |
| 280 | +endif::[] |
| 281 | + |
| 282 | +[NOTE] |
| 283 | +==== |
| 284 | +The CNI plugin at version `1.x` is compatible with `Istio` at version `1.x-1`, `1.x` and `1.x+1`. |
| 285 | +==== |
| 286 | + |
| 287 | +[#resource-status] |
| 288 | +=== Resource Status |
| 289 | + |
| 290 | +All of the Sail Operator API resources have a `status` subresource that contains information about their current state in the Kubernetes cluster. |
| 291 | + |
| 292 | +[#conditions] |
| 293 | +==== Conditions |
| 294 | + |
| 295 | +All resources have a `Ready` condition which is set to `true` as soon as all child resource have been created and are deemed Ready by their respective controllers. To see additional conditions for each of the resources, check the link:api-reference/sailoperator.io.adoc[API reference documentation]. |
| 296 | + |
| 297 | +[#inuse-detection] |
| 298 | +==== InUse Detection |
| 299 | + |
| 300 | +The Sail Operator uses InUse detection to determine whether an object is referenced. This is currently present on all resources apart from `IstioCNI`. On the `Istio` resource, it is a counter as it only aggregates the `InUse` conditions on its child `IstioRevisions`. |
| 301 | + |
| 302 | +[cols="3,2,3,8"] |
| 303 | +|=== |
| 304 | +|API |Type |Name |Description |
| 305 | + |
| 306 | +|Istio |
| 307 | +|Counter |
| 308 | +|Status.Revisions.InUse |
| 309 | +|Aggregates across all child `IstioRevisions`. |
| 310 | + |
| 311 | +|IstioRevision |
| 312 | +|Condition |
| 313 | +|Status.Conditions[type="InUse'] |
| 314 | +|Set to `true` if the `IstioRevision` is referenced by a namespace, workload or `IstioRevisionTag`. |
| 315 | + |
| 316 | +|IstioRevisionTag |
| 317 | +|Condition |
| 318 | +|Status.Conditions[type="InUse'] |
| 319 | +|Set to `true` if the `IstioRevisionTag` is referenced by a namespace or workload. |
| 320 | +|=== |
| 321 | + |
| 322 | +[#api-reference-documentation] |
| 323 | +== API Reference documentation |
| 324 | + |
| 325 | +The Sail Operator API reference documentation can be found link:api-reference/sailoperator.io.adoc#api-reference[here]. |
| 326 | + |
| 327 | +== AI Agents Guide |
| 328 | + |
| 329 | +For developers using AI coding assistants (Claude, GitHub Copilot, Cursor, etc.), see the link:ai/ai-agents-guide.adoc[AI Agents Guide] for information on how to configure and use the Sail Operator's AI agent context files. |
0 commit comments